def deep_merge_directory(self, base, merger, clean=False):
		"""Merge folder 'merger' into 'base' without deleting existing"""
		if not os.path.exists(base):
			self.print_verbose("Base path does not exist:" + str(base))
			return -1
		elif not os.path.exists(merger):
			self.print_verbose("Merger path does not exist")
			return -1

		# Path to be aware of and not overwrite/remove/etc.
		staging_path = os.path.join(self._updater_path, "update_staging")

		# If clean install is enabled, clear existing files ahead of time
		# note: will not delete the update.json, update folder, staging, or
		# staging but will delete all other folders/files in addon directory.
		error = None
		if clean:
			try:
				# Implement clearing of all folders/files, except the updater
				# folder and updater json.
				# Careful, this deletes entire subdirectories recursively...
				# Make sure that base is not a high level shared folder, but
				# is dedicated just to the addon itself.
				self.print_verbose(
					"clean=True, clearing addon folder to fresh install state")

				# Remove root files and folders (except update folder).
				files = [f for f in os.listdir(base)
						 if os.path.isfile(os.path.join(base, f))]
				folders = [f for f in os.listdir(base)
						   if os.path.isdir(os.path.join(base, f))]

				for f in files:
					os.remove(os.path.join(base, f))
					self.print_verbose(
						"Clean removing file {}".format(os.path.join(base, f)))
				for f in folders:
					if os.path.join(base, f) is self._updater_path:
						continue
					shutil.rmtree(os.path.join(base, f))
					self.print_verbose(
						"Clean removing folder and contents {}".format(
							os.path.join(base, f)))

			except Exception as err:
				error = "failed to create clean existing addon folder"
				print(error, str(err))
				self.print_trace()

		# Walk through the base addon folder for rules on pre-removing
		# but avoid removing/altering backup and updater file.
		for path, dirs, files in os.walk(base):
			# Prune ie skip updater folder.
			dirs[:] = [d for d in dirs
					   if os.path.join(path, d) not in [self._updater_path]]
			for file in files:
				for pattern in self.remove_pre_update_patterns:
					if fnmatch.filter([file], pattern):
						try:
							fl = os.path.join(path, file)
							os.remove(fl)
							self.print_verbose("Pre-removed file " + file)
						except OSError:
							print("Failed to pre-remove " + file)
							self.print_trace()

		# Walk through the temp addon sub folder for replacements
		# this implements the overwrite rules, which apply after
		# the above pre-removal rules. This also performs the
		# actual file copying/replacements.
		for path, dirs, files in os.walk(merger):
			# Verify structure works to prune updater sub folder overwriting.
			dirs[:] = [d for d in dirs
					   if os.path.join(path, d) not in [self._updater_path]]
			rel_path = os.path.relpath(path, merger)
			dest_path = os.path.join(base, rel_path)
			if not os.path.exists(dest_path):
				os.makedirs(dest_path)
			for file in files:
				# Bring in additional logic around copying/replacing.
				# Blender default: overwrite .py's, don't overwrite the rest.
				dest_file = os.path.join(dest_path, file)
				srcFile = os.path.join(path, file)

				# Decide to replace if file already exists, and copy new over.
				if os.path.isfile(dest_file):
					# Otherwise, check each file for overwrite pattern match.
					replaced = False
					for pattern in self._overwrite_patterns:
						if fnmatch.filter([file], pattern):
							replaced = True
							break
					if replaced:
						os.remove(dest_file)
						os.rename(srcFile, dest_file)
						self.print_verbose(
							"Overwrote file " + os.path.basename(dest_file))
					else:
						self.print_verbose(
							"Pattern not matched to {}, not overwritten".format(
								os.path.basename(dest_file)))
				else:
					# File did not previously exist, simply move it over.
					os.rename(srcFile, dest_file)
					self.print_verbose(
						"New file " + os.path.basename(dest_file))

		# now remove the temp staging folder and downloaded zip
		try:
			shutil.rmtree(staging_path)
		except:
			error = ("Error: Failed to remove existing staging directory, "
					 "consider manually removing ") + staging_path
			self.print_verbose(error)
			self.print_trace()