docs: def send_file(self,
  	              path,
  	              contents,
  	              echo=False,
  	              truncate=False,
  	              note=None,
  	              user=None,
  	              group=None,
  	              loglevel=logging.INFO,
  	              encoding=None):
  		"""Sends the passed-in string as a file to the passed-in path on the
  		target.
  
  		@param path:        Target location of file on target.
  		@param contents:    Contents of file as a string.
  		@param note:        See send()
  		@param user:        Set ownership to this user (defaults to whoami)
  		@param group:       Set group to this user (defaults to first group in groups)
  
  		@type path:         string
  		@type contents:     string
  		"""
  		shutit = self.shutit
  		shutit.handle_note(note, 'Sending contents to path: ' + path)
  		# make more efficient by only looking at first 10000 chars, stop when we get to 30 chars rather than reading whole file.
  		if shutit_global.shutit_global_object.ispy3:
  			split_contents = ''.join((str(contents[:10000]).split()))
  		else:
  			split_contents = ''.join((contents[:10000].split()))
  		strings_from_file = re.findall("[^\x00-\x1F\x7F-\xFF]", split_contents)
  		shutit.log('Sending file contents beginning: "' + ''.join(strings_from_file)[:30] + ' [...]" to file: ' + path, level=loglevel)
  		if user is None:
  			user = self.whoami()
  		if group is None:
  			group = self.whoarewe()
  		if self.current_environment.environment_id == 'ORIGIN_ENV' and False:
  			# If we're on the root env (ie the same one that python is running on, then use python.
  			if isinstance(contents, str):
  				f = open(path,'w')
  				if truncate:
  					f.truncate(0)
  				try:
  					f.write(contents)
  				except (UnicodeDecodeError, TypeError) as e:
  					shutit.log('Error decoding: ' + str(e), level=logging.DEBUG)
  					if encoding is not None:
  						f.write(contents.decode(encoding))
  					else:
  						f.write(contents.decode(shutit_global.shutit_global_object.default_encoding))
  			elif isinstance(contents, bytes):
  				f = open(path,'w')
  				if truncate:
  					f.truncate(0)
  				try:
  					f.write(contents)
  				except (UnicodeDecodeError, TypeError) as e:
  					if encoding is not None:
  						f.write(contents.decode(encoding))
  					else:
  						f.write(contents.decode(shutit_global.shutit_global_object.default_encoding))
  			else:
  				shutit.fail('type: ' + str(type(contents)) + ' not handled in 1') # pragma: no cover
  			f.close()
  		elif shutit.build['delivery'] in ('bash','dockerfile'):
  			if truncate and self.file_exists(path):
  				self.send(ShutItSendSpec(self,
  				                         send=' command rm -f ' + path,
  				                         echo=False,
  				                         loglevel=loglevel,
  				                         ignore_background=True))
  			random_id = shutit_util.random_id()
  			# set the searchwindowsize to a low number to speed up processing of large output
  			if shutit_global.shutit_global_object.ispy3:
  				if encoding is not None:
  					b64contents = base64.b64encode(contents.encode(encoding)).decode(encoding)
  				else:
  					if isinstance(contents, str):
  						b64contents = base64.b64encode(contents.encode(shutit_global.shutit_global_object.default_encoding)).decode(shutit_global.shutit_global_object.default_encoding)
  					elif isinstance(contents, bytes):
  						b64contents = base64.b64encode(contents).decode(shutit_global.shutit_global_object.default_encoding)
  					else:
  						shutit.fail('type: ' + str(type(contents)) + ' not handled in 2') # pragma: no cover
  			else:
  				if encoding is not None:
  					b64contents = base64.b64encode(contents.encode(encoding))
  				else:
  					b64contents = base64.b64encode(contents.encode(shutit_global.shutit_global_object.default_encoding))
  			# split the contents into chunks and append to avoid PC_MAX_CANON: see https://github.com/pexpect/pexpect/commit/f3ef67b6ba5508d0d118b59837d099f5144e576b
  			total_length = len(b64contents)
  			position = 0
  			leap=1000
  			while position < total_length:
  				self.send(ShutItSendSpec(self,
  				                         send=' ' + shutit.get_command('head') + ' -c -1 >> ' + path + "." + random_id + " << 'END_" + random_id + """'\n""" + b64contents[position:position+leap] + '''\nEND_''' + random_id,
  				                         echo=echo,
  				                         loglevel=loglevel,
  				                         timeout=shutit_global.shutit_global_object.default_timeout,
  				                         ignore_background=True))
  				position += leap
  			self.send(ShutItSendSpec(self,
  			                         send=' command cat ' + path + '.' + random_id + ' | base64 --decode > ' + path,
  			                         echo=echo,
  			                         loglevel=loglevel,
  			                         ignore_background=True))
  			# Remove the file
  			self.send(ShutItSendSpec(self,
  			                         send=' command rm -f ' + path + '.' + random_id,
  			                         loglevel=loglevel,
  			                         echo=False,
  			                         ignore_background=True))
  		else:
  			host_child = shutit.get_shutit_pexpect_session_from_id('host_child').pexpect_child
  			path = path.replace(' ', r'\ ')
  			# get host session
  			tmpfile = shutit_global.shutit_global_object.shutit_state_dir + 'tmp_' + shutit_util.random_id()
  			f = open(tmpfile,'wb')
  			f.truncate(0)
  			# TODO: try taking out trys
  			if isinstance(contents, bytes):
  				try:
  					if shutit_global.shutit_global_object.ispy3:
  						f.write(contents)
  					elif encoding is not None:
  						f.write(contents.encode(encoding))
  					else:
  						f.write(contents.encode(shutit_global.shutit_global_object.default_encoding))
  				except (UnicodeDecodeError, TypeError) as e:
  					f.write(contents)
  			else:
  				# We assume it's unicode, or str. Can't be explicit because python3 and 2 differ in how they handle...
  				try:
  					if encoding is not None:
  						f.write(contents.encode(encoding))
  					else:
  						f.write(contents.encode(shutit_global.shutit_global_object.default_encoding))
  				except (UnicodeDecodeError, TypeError) as e:
  					f.write(contents)
  			f.close()
  			# Create file so it has appropriate permissions
  			self.send(ShutItSendSpec(self,
  			                         send=' command touch ' + path,
  			                         loglevel=loglevel,
  			                         echo=echo,
  			                         ignore_background=True))
  			# If path is not absolute, add $HOME to it.
  			if path[0] != '/':
  				shutit.send(' command cat ' + tmpfile + ' | ' + shutit.host['docker_executable'] + ' exec -i ' + shutit.target['container_id'] + " bash -c 'cat > $HOME/" + path + "'",
  				            shutit_pexpect_child=host_child,
  				            expect=shutit.expect_prompts['ORIGIN_ENV'],
  				            loglevel=loglevel,
  				            echo=echo)
  			else:
  				shutit.send(' command cat ' + tmpfile + ' | ' + shutit.host['docker_executable'] + ' exec -i ' + shutit.target['container_id'] + " bash -c 'cat > " + path + "'",
  				            shutit_pexpect_child=host_child,
  				            expect=shutit.expect_prompts['ORIGIN_ENV'],
  				            loglevel=loglevel,
  				            echo=echo)
  			self.send(ShutItSendSpec(self,
  			                         send=' command chown ' + user + ' ' + path + ' && chgrp ' + group + ' ' + path,
  			                         echo=echo,
  			                         loglevel=loglevel,
  			                         ignore_background=True))
  			os.remove(tmpfile)
  		shutit.handle_note_after(note=note)
  		return True