mirror of
https://github.com/ARM-software/devlib.git
synced 2025-09-23 04:11:54 +01:00
target: Factorize push/pull path resolution
Handle in one place the decision of what is the real destination of each file in push/pull operations. The following can now be assumed by the connection: * The destination does not exist. * The folder containing the destination does exist. This ensures consistent errors and behaviors across all connection types, at the cost of: * At least an extra execute() per source (up to 2 if the destination is a file that needs to be removed to make room). * For now, globbing will lead to a separate request for each file, rather than a merged one. This is because the destination of each source is prepared so that the connection will not have any interpretation work to do.
This commit is contained in:
committed by
Marc Bonnici
parent
79be8bc5ad
commit
173df18f29
@@ -315,6 +315,7 @@ class AdbConnection(ConnectionBase):
|
||||
return self._push_pull('pull', sources, dest, timeout)
|
||||
|
||||
def _push_pull(self, action, sources, dest, timeout):
|
||||
sources = list(sources)
|
||||
paths = sources + [dest]
|
||||
|
||||
# Quote twice to avoid expansion by host shell, then ADB globbing
|
||||
|
@@ -424,26 +424,7 @@ class SshConnection(SshConnectionBase):
|
||||
return SCPClient(self.client.get_transport(), socket_timeout=timeout, progress=self._get_progress_cb())
|
||||
|
||||
def _push_file(self, sftp, src, dst):
|
||||
try:
|
||||
sftp.put(src, dst, callback=self._get_progress_cb())
|
||||
# Maybe the dst was a folder
|
||||
except OSError as orig_excep:
|
||||
# If dst was an existing folder, we add the src basename to create
|
||||
# a new destination for the file as cp would do
|
||||
new_dst = os.path.join(
|
||||
dst,
|
||||
os.path.basename(src),
|
||||
)
|
||||
logger.debug('Trying: {} -> {}'.format(src, new_dst))
|
||||
try:
|
||||
sftp.put(src, new_dst, callback=self._get_progress_cb())
|
||||
# This still failed, which either means:
|
||||
# * There are some missing folders in the dirnames
|
||||
# * Something else SFTP-related is wrong
|
||||
except OSError as e:
|
||||
# Raise the original exception, as it is closer to what the
|
||||
# user asked in the first place
|
||||
raise orig_excep
|
||||
sftp.put(src, dst, callback=self._get_progress_cb())
|
||||
|
||||
@classmethod
|
||||
def _path_exists(cls, sftp, path):
|
||||
@@ -455,29 +436,13 @@ class SshConnection(SshConnectionBase):
|
||||
return True
|
||||
|
||||
def _push_folder(self, sftp, src, dst):
|
||||
# Behave like the "mv" command or adb push: a new folder is created
|
||||
# inside the destination folder, rather than merging the trees, but
|
||||
# only if the destination already exists. Otherwise, it is use as-is as
|
||||
# the new hierarchy name.
|
||||
if self._path_exists(sftp, dst):
|
||||
dst = os.path.join(
|
||||
dst,
|
||||
os.path.basename(os.path.normpath(src)),
|
||||
)
|
||||
|
||||
return self._push_folder_internal(sftp, src, dst)
|
||||
|
||||
def _push_folder_internal(self, sftp, src, dst):
|
||||
# This might fail if the folder already exists
|
||||
with contextlib.suppress(IOError):
|
||||
sftp.mkdir(dst)
|
||||
|
||||
sftp.mkdir(dst)
|
||||
for entry in os.scandir(src):
|
||||
name = entry.name
|
||||
src_path = os.path.join(src, name)
|
||||
dst_path = os.path.join(dst, name)
|
||||
if entry.is_dir():
|
||||
push = self._push_folder_internal
|
||||
push = self._push_folder
|
||||
else:
|
||||
push = self._push_file
|
||||
|
||||
@@ -489,25 +454,9 @@ class SshConnection(SshConnectionBase):
|
||||
push(sftp, src, dst)
|
||||
|
||||
def _pull_file(self, sftp, src, dst):
|
||||
# Pulling a file into a folder will use the source basename
|
||||
if os.path.isdir(dst):
|
||||
dst = os.path.join(
|
||||
dst,
|
||||
os.path.basename(src),
|
||||
)
|
||||
|
||||
with contextlib.suppress(FileNotFoundError):
|
||||
os.remove(dst)
|
||||
|
||||
sftp.get(src, dst, callback=self._get_progress_cb())
|
||||
|
||||
def _pull_folder(self, sftp, src, dst):
|
||||
with contextlib.suppress(FileNotFoundError):
|
||||
try:
|
||||
shutil.rmtree(dst)
|
||||
except OSError:
|
||||
os.remove(dst)
|
||||
|
||||
os.makedirs(dst)
|
||||
for fileattr in sftp.listdir_attr(src):
|
||||
filename = fileattr.filename
|
||||
@@ -836,7 +785,7 @@ class TelnetConnection(SshConnectionBase):
|
||||
def push(self, sources, dest, timeout=30):
|
||||
# Quote the destination as SCP would apply globbing too
|
||||
dest = self.fmt_remote_path(quote(dest))
|
||||
paths = sources + [dest]
|
||||
paths = list(sources) + [dest]
|
||||
return self._scp(paths, timeout)
|
||||
|
||||
def pull(self, sources, dest, timeout=30):
|
||||
@@ -1113,9 +1062,6 @@ class Gem5Connection(TelnetConnection):
|
||||
# We need to copy the file to copy to the temporary directory
|
||||
self._move_to_temp_dir(source)
|
||||
|
||||
# Dest in gem5 world is a file rather than directory
|
||||
if os.path.basename(dest) != filename:
|
||||
dest = os.path.join(dest, filename)
|
||||
# Back to the gem5 world
|
||||
filename = quote(self.gem5_input_dir + filename)
|
||||
self._gem5_shell("ls -al {}".format(filename))
|
||||
|
Reference in New Issue
Block a user