Giter Club home page Giter Club logo

better-adb-sync's Introduction

Jay Berry / jb2170

25 year old mathematician and programmer with a strong background in Artificial Intelligence and Statistics

Studies

University of Cambridge Mathematics Tripos MA Honorary (2024)
Manchester Metropolitan University Artificial Intelligence MSc Distinction (2022-2023)
University of Cambridge Mathematics Tripos BA Senior Optime (2017-2020)

Programming

I use Arch Linux as my daily driver and I primarily program in Python and C++.

I have over 10 years experience using many languages, frameworks, and tools including:

✓ Python (primary) ✓ C++ (secondary) ✓ C ✓ Bash ✓ Linux
✓ Hugo ✓ C# ✓ Docker ✓ Git $\LaTeX$
✓ HTML ✓ CSS ✓ JavaScript ✓ TypeScript ✓ React
✓ SQL ✓ NodeJS

Languages

Actively learning modern Hebrew, עברית, for 2 years

I am familiar with the following:

🇬🇧 - Native 🇮🇱 - Intermediate 🇻🇦 (Latin) - ALevel
🇬🇷 (Ancient) - GCSE 🇩🇪 - GCSE 🇷🇺 - Beginners

Links

> www.jb2170.com
> GitHub
> LinkedIn

better-adb-sync's People

Contributors

chatziko avatar cng avatar cryptogopher avatar divverent avatar jb2170 avatar jottr avatar qezt avatar thiblahute avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

better-adb-sync's Issues

Skip Files with Errors

Especially on Windows, inevitably there's some file/folder with a filename that Windows doesn't like for one reason or another, and adb pull . It'd be nice if there was a way to get adb-sync to just skip files that give an error, instead of the whole process exiting over it. A way to log the errors would be nice, but at least being able to skip those issues would be appreciated.

Publish on PyPI

better-adb-sync would be even better than adb-sync if it was on pypi.org. I would like to be able to run a simple pip install better-adb-sync, possibly locally in a venv, and then do (better-)?adb-sync right away. This would allow users to easily update and version this program.

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 56: invalid start byte

Traceback (most recent call last):
  File "/usr/local/bin/adbsync", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/usr/local/lib/python3.11/site-packages/BetterADBSync/__init__.py", line 379, in main
    files_tree_destination = fs_destination.get_files_tree(path_destination, follow_links = args.copy_links)
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/BetterADBSync/FileSystems/Base.py", line 45, in get_files_tree
    return self._get_files_tree(tree_path, statObject, follow_links = follow_links)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/BetterADBSync/FileSystems/Base.py", line 33, in _get_files_tree
    tree[filename] = self._get_files_tree(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/BetterADBSync/FileSystems/Base.py", line 30, in _get_files_tree
    for filename, stat_object_child, in self.lstat_in_dir(tree_path):
  File "/usr/local/lib/python3.11/site-packages/BetterADBSync/FileSystems/Android.py", line 176, in lstat_in_dir
    for line in self.adb_shell(["ls", "-la", path]):
  File "/usr/local/lib/python3.11/site-packages/BetterADBSync/FileSystems/Android.py", line 87, in adb_shell
    adb_line = adb_line.decode(self.adb_encoding).rstrip("\r\n")
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 56: invalid start byte

After adbsync push failed. rerun adbsync push get this error.

ADB line not captured ?

Getting this error:

debian:~/rlm-rz$ adb-sync --pull /storage/emulated/0 .
ADB line not captured
ls: ./apex: Permission denied
Stack (most recent call last):
  File "/home/rz/bin/adb-sync", line 6, in <module>
    ADBSync.main()
  File "/home/rz/prog/better-adb-sync/src/ADBSync/__init__.py", line 364, in main
    files_tree_source = fs_source.get_files_tree(path_source, follow_links = argargs.copy_links)
  File "/home/rz/prog/better-adb-sync/src/ADBSync/FileSystems/Base.py", line 45, in get_files_tree
    return self._get_files_tree(tree_path, statObject, follow_links = follow_links)
  File "/home/rz/prog/better-adb-sync/src/ADBSync/FileSystems/Base.py", line 33, in _get_files_tree
    tree[filename] = self._get_files_tree(
  File "/home/rz/prog/better-adb-sync/src/ADBSync/FileSystems/Base.py", line 30, in _get_files_tree
    for filename, stat_object_child, in self.lstat_in_dir(tree_path):
  File "/home/rz/prog/better-adb-sync/src/ADBSync/FileSystems/Android.py", line 190, in lstat_in_dir
    yield self.ls_to_stat(line)
  File "/home/rz/prog/better-adb-sync/src/ADBSync/FileSystems/Android.py", line 153, in ls_to_stat
    self.line_not_captured(line)
  File "/home/rz/prog/better-adb-sync/src/ADBSync/FileSystems/Android.py", line 103, in line_not_captured
    logging_fatal(line)

adb shell, adb logcat etc work fine. Previously used original adb-sync which stopped working with a "connection reset by peer" so tried your variant. Don't know when exactly it stopped working but possibly after a supposedly minor Android update.

TIA

Support full backups of /sdcard

Hi,

Due to followLinks being False, running backups of /sdcard without specifying a deeper directory fails.

/sdcard/[directory] works fine, but it ignores /sdcard due to it being a symlink.

python adbsync.py --pull --adb-flag a 'J:\GalaxyS10BackupsAug2021newer\Apr32022\sdcard\' /sdcard --exclude MyVerizon  --show-progress
[WARNING] Ignoring symlink '/sdcard'

Note:
A potential solution is to use /storage/emulated/0 instead, but sometimes the permissions for this directory do not work/are not set properly over ADB, causing a permission denied error. /sdcard seems to be more consistent, even if it is just a link.

Regardless, it seems there are some issues still with using that.

Traceback (most recent call last):
  File "adbsync.py", line 6, in <module>
    ADBSync.main()
  File "J:\GalaxyS10BackupsAug2021newer\ADBSync\src\ADBSync\__init__.py", line 369, in main
    filesTree_source = fs_source.getFilesTree(path_source, followLinks = args.copyLinks)
  File "J:\GalaxyS10BackupsAug2021newer\ADBSync\src\ADBSync\FileSystems\Base.py", line 55, in getFilesTree
    return self._getFilesTree(tree_root, statObject, followLinks = followLinks)
  File "J:\GalaxyS10BackupsAug2021newer\ADBSync\src\ADBSync\FileSystems\Base.py", line 43, in _getFilesTree
    tree[filename] = self._getFilesTree(
  File "J:\GalaxyS10BackupsAug2021newer\ADBSync\src\ADBSync\FileSystems\Base.py", line 40, in _getFilesTree
    for filename, statObject_child, in self.lstat_inDir(tree_root):
  File "J:\GalaxyS10BackupsAug2021newer\ADBSync\src\ADBSync\FileSystems\Android.py", line 146, in lstat_inDir
    for line in self.adbShell(["ls", "-la", self.escapePath(path)]):
  File "J:\GalaxyS10BackupsAug2021newer\ADBSync\src\ADBSync\FileSystems\Base.py", line 17, in adbShell
    adbLine = adbLine.decode().rstrip("\r\n")
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x96 in position 76: invalid start byte

Software:

Android Debug Bridge version 1.0.41
Version 33.0.1-8253317
Python 3.8.2
Windows Version 10.0.19044 Build 19044

AttributeError: 'AndroidFileSystem' object has no attribute 'proc_adb_shell'

Traceback (most recent call last):
  File "/Users/bart/.local/bin/adbsync", line 10, in <module>
    sys.exit(main())
             ^^^^^^
  File "/Users/bart/Library/Application Support/pipx/venvs/betteradbsync/lib/python3.12/site-packages/BetterADBSync/__init__.py", line 349, in main
    fs_android = AndroidFileSystem(adb_arguments, args.adb_encoding)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bart/Library/Application Support/pipx/venvs/betteradbsync/lib/python3.12/site-packages/BetterADBSync/FileSystems/Android.py", line 67, in __init__
    self.proc_adb_shell = subprocess.Popen(
                          ^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/[email protected]/3.12.2_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/subprocess.py", line 1026, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/opt/homebrew/Cellar/[email protected]/3.12.2_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/subprocess.py", line 1953, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'adb'
Exception ignored in: <function AndroidFileSystem.__del__ at 0x1006596c0>
Traceback (most recent call last):
  File "/Users/bart/Library/Application Support/pipx/venvs/betteradbsync/lib/python3.12/site-packages/BetterADBSync/FileSystems/Android.py", line 75, in __del__
    self.proc_adb_shell.stdin.close()
    ^^^^^^^^^^^^^^^^^^^
AttributeError: 'AndroidFileSystem' object has no attribute 'proc_adb_shell'

when pull, files is sync to different dir for first time and second time

when use pull, eg: pull /sdcard/b /a/b
when execute for the first time, the files in /sdcard/b is sync to /a/b;
then execute again, the files in /sdcard/b is sync to /a/b/b;
I dont known whether this is because the first time /a/b is not exists, and the second time /a/b has bean created.

is this an issue, or I run this script on a wrong way?

cannot use args like --exclude or --show-progress

I am getting these errors with adbsync 1.3.2:

$ adbsync pull /sdcard/DCIM . --show-progress
usage: adbsync [-h] [--version] [--no-color] [-v | -q] [-n] [-L] [--exclude EXCLUDE] [--exclude-from EXCLUDE_FROM] [--del] [--delete-excluded] [--force] [--show-progress] [--adb-encoding ADB_ENCODING] [--adb-bin ADB_BIN]
               [--adb-flag ADB_FLAG] [--adb-option OPTION VALUE]
               {push,pull} ...
adbsync: error: unrecognized arguments: --show-progress
$ adbsync pull /sdcard/* . --exclude Android
usage: adbsync [-h] [--version] [--no-color] [-v | -q] [-n] [-L] [--exclude EXCLUDE] [--exclude-from EXCLUDE_FROM] [--del] [--delete-excluded] [--force] [--show-progress] [--adb-encoding ADB_ENCODING] [--adb-bin ADB_BIN]
               [--adb-flag ADB_FLAG] [--adb-option OPTION VALUE]
               {push,pull} ...
adbsync: error: unrecognized arguments: --exclude Android

[CRITICAL] Connection test failed [CRITICAL] Exiting

Hello,

I'm trying to use your utility to sync my music library from my Windows computer to my Android phone but without success.

I'm running better-adb-sync 1.4.

When I type adbsync push "C:/Users/Tom/Downloads/1-Music/4-Phone" "/sdcard/Music"
I get the following message:

</dev/null
[CRITICAL] Connection test failed
[CRITICAL] Exiting

(if my device is unplugged, I get this: error: device not found)
Then nothing happens, so I have to cancel with ctrl+c and I get this error message:

Exception ignored in: <function AndroidFileSystem.__del__ at 0x0000029AB171C4A0>
Traceback (most recent call last):
  File "C:\Users\Tom\AppData\Local\Programs\Python\Python312\Lib\site-packages\BetterADBSync\FileSystems\Android.py", line 76, in __del__
    self.proc_adb_shell.wait()
  File "C:\Users\Tom\AppData\Local\Programs\Python\Python312\Lib\subprocess.py", line 1264, in wait
    return self._wait(timeout=timeout)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Tom\AppData\Local\Programs\Python\Python312\Lib\subprocess.py", line 1588, in _wait
    result = _winapi.WaitForSingleObject(self._handle,
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
KeyboardInterrupt:

Am I doing something wrong?

Thanks in advance!

when tried to backup android/media/com.whatsapp getting the following error

Traceback (most recent call last): File "C:\DATA\PB\better-adb-sync\src\adbsync.py", line 6, in <module> ADBSync.main() File "C:\DATA\PB\better-adb-sync\src\ADBSync\__init__.py", line 374, in main files_tree_source = fs_source.get_files_tree(path_source, follow_links = args.copy_links) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\DATA\PB\better-adb-sync\src\ADBSync\FileSystems\Base.py", line 45, in get_files_tree return self._get_files_tree(tree_path, statObject, follow_links = follow_links) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\DATA\PB\better-adb-sync\src\ADBSync\FileSystems\Base.py", line 33, in _get_files_tree tree[filename] = self._get_files_tree( ^^^^^^^^^^^^^^^^^^^^^ File "C:\DATA\PB\better-adb-sync\src\ADBSync\FileSystems\Base.py", line 33, in _get_files_tree tree[filename] = self._get_files_tree( ^^^^^^^^^^^^^^^^^^^^^ File "C:\DATA\PB\better-adb-sync\src\ADBSync\FileSystems\Base.py", line 33, in _get_files_tree tree[filename] = self._get_files_tree( ^^^^^^^^^^^^^^^^^^^^^ [Previous line repeated 2 more times] File "C:\DATA\PB\better-adb-sync\src\ADBSync\FileSystems\Android.py", line 192, in lstat_in_dir yield self.ls_to_stat(line) File "C:\DATA\PB\better-adb-sync\src\ADBSync\FileSystems\Android.py", line 94, in adb_shell adb_line = adb_line.decode(self.adb_encoding).rstrip("\r\n") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 83: invalid start byte

Problem with Korean and Japanese characters in filename (my guess) - 'utf-8' codec can't decode byte

File "...\better-adb-sync-master\src\adbsync.py", line 6, in
ADBSync.main()
File "...\better-adb-sync-master\src\ADBSync_init_.py", line 364, in main
files_tree_source = fs_source.get_files_tree(path_source, follow_links = args.copy_links)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "...\better-adb-sync-master\src\ADBSync\FileSystems\Base.py", line 45, in get_files_tree
return self._get_files_tree(tree_path, statObject, follow_links = follow_links)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "...\better-adb-sync-master\src\ADBSync\FileSystems\Base.py", line 33, in _get_files_tree
tree[filename] = self._get_files_tree(
^^^^^^^^^^^^^^^^^^^^^
File "...\better-adb-sync-master\src\ADBSync\FileSystems\Base.py", line 33, in _get_files_tree
tree[filename] = self._get_files_tree(
^^^^^^^^^^^^^^^^^^^^^
File "...\better-adb-sync-master\src\ADBSync\FileSystems\Base.py", line 33, in _get_files_tree
tree[filename] = self._get_files_tree(
^^^^^^^^^^^^^^^^^^^^^
File "...\better-adb-sync-master\src\ADBSync\FileSystems\Base.py", line 30, in _get_files_tree
for filename, stat_object_child, in self.lstat_in_dir(tree_path):
File "...\better-adb-sync-master\src\ADBSync\FileSystems\Android.py", line 186, in lstat_in_dir
for line in self.adb_shell(["ls", "-la", self.escape_path(path)]):
File "...\better-adb-sync-master\src\ADBSync\FileSystems\Android.py", line 93, in adb_shell
adb_line = adb_line.decode().rstrip("\r\n")
^^^^^^^^^^^^^^^^^
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x92 in position 77: invalid start byte

Errors while syncing - File "<frozen runpy>" - UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0

Here is the error message I get:
C:\Users\Tom>adbsync push "F:\1-Music\3-Music Phone\Music" "/sdcard/"

* daemon not running; starting now at tcp:5037
* daemon started successfully
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\Users\Tom\AppData\Roaming\Python\Python312\Scripts\adbsync.exe\__main__.py", line 7, in <module>
  File "C:\Users\Tom\AppData\Roaming\Python\Python312\site-packages\BetterADBSync\__init__.py", line 379, in main
    files_tree_destination = fs_destination.get_files_tree(path_destination, follow_links = args.copy_links)
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Tom\AppData\Roaming\Python\Python312\site-packages\BetterADBSync\FileSystems\Base.py", line 45, in get_files_tree
    return self._get_files_tree(tree_path, statObject, follow_links = follow_links)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Tom\AppData\Roaming\Python\Python312\site-packages\BetterADBSync\FileSystems\Base.py", line 33, in _get_files_tree
    tree[filename] = self._get_files_tree(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Tom\AppData\Roaming\Python\Python312\site-packages\BetterADBSync\FileSystems\Base.py", line 33, in _get_files_tree
    tree[filename] = self._get_files_tree(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Tom\AppData\Roaming\Python\Python312\site-packages\BetterADBSync\FileSystems\Base.py", line 33, in _get_files_tree
    tree[filename] = self._get_files_tree(
                     ^^^^^^^^^^^^^^^^^^^^^
  [Previous line repeated 2 more times]
  File "C:\Users\Tom\AppData\Roaming\Python\Python312\site-packages\BetterADBSync\FileSystems\Base.py", line 30, in _get_files_tree
    for filename, stat_object_child, in self.lstat_in_dir(tree_path):
  File "C:\Users\Tom\AppData\Roaming\Python\Python312\site-packages\BetterADBSync\FileSystems\Android.py", line 176, in lstat_in_dir
    for line in self.adb_shell(["ls", "-la", path]):
  File "C:\Users\Tom\AppData\Roaming\Python\Python312\site-packages\BetterADBSync\FileSystems\Android.py", line 87, in adb_shell
    adb_line = adb_line.decode(self.adb_encoding).rstrip("\r\n")
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 71: invalid start byte

Additional info: when using "adb push", I get errors when my files' path is too long, so maybe there's a similar issue with better-adb-sync?

I'm not familar with Python debugging so let me know if you need anything else.

Thank you!

Please follow rsync convention

This script does not treat a trailing slash on the source side's filepath specially.

I would place a request to reconsider using rsync's behaviour of trailing slash in source. That is such a convention and will help a lot.

invalid syntax

Don't know if I'm just running it wrong or something (using any kind of option), but whenever I run it I get the following

Traceback (most recent call last):
File "./adbsync.py", line 3, in
import ADBSync
File "/home/Mac/better-adb-sync/src/ADBSync/init.py", line 16, in
from .FileSystems.Local import LocalFileSystem
File "/home/Mac/better-adb-sync/src/ADBSync/FileSystems/Local.py", line 10, in
from .Base import FileSystem
File "/home/Mac/better-adb-sync/src/ADBSync/FileSystems/Base.py", line 18
while adbLine := proc.stdout.readline():
^
SyntaxError: invalid syntax

Edit: this is running on a NAS running Debian Server, with Python3 installed

Fatal Exit

Might be missing something but can we not run this from the src directory?

[babak@bbox-arch src]$ python --version
Python 3.10.8

[babak@bbox-arch src]$ python adbsync.py --pull --force --show-progress /sdcard /home/babak/Pixel4XL/sdcard/ 
/home/babak/Pixel4XL/sdcard: None
Stack (most recent call last):
  File "/home/babak/Pixel4XL/better-adb-sync/src/adbsync.py", line 6, in <module>
    ADBSync.main()
  File "/home/babak/Pixel4XL/better-adb-sync/src/ADBSync/__init__.py", line 366, in main
    perror(path_source, e, FATAL)
  File "/home/babak/Pixel4XL/better-adb-sync/src/ADBSync/SAOLogging.py", line 95, in perror
    logging_fatal(msg)
  File "/home/babak/Pixel4XL/better-adb-sync/src/ADBSync/SAOLogging.py", line 63, in logging_fatal
    logging.critical(message, stack_info = log_stack_info)
Exiting

Please update the documentation

The documentation on the main page reflecting how the original adb-sync worked is confusing and misleading as applied to this rewrite, given that the current adbsync works very differently in some ways that aren't really explained. For example, I used to use adb-sync to back up my camera images like so:

adb-sync -R -n /sdcard/DCIM/ /home/frank/pictures/cellphone_Images/current

where "-R" meant reverse, and "-n" meant no-clobber. Nowhere on the main page is it shown that "--reverse" has been replaced with "--pull", and "-n" now means "dry-run" and there doesn't appear to be a no-clobber option (although it appears, but it isn't stated outright, that not clobbering is the default unless "--del" is passed). Also, the ordering of target and destination directories has changed. So the replacement command would be:

adbsync --pull /home/frank/pictures/cellphone_Images/test /sdcard/DCIM/

...but it took some effort to figure that out. For anybody switching from the original adb-sync, this is likely to be quite confusing (and this is just one example, I'm sure there are plenty of others).

Timezone bug forcing a full re-sync

adb-sync keep resyncing all my files. I checked, and the timestamp on the phone is exactly of N hours, and I'm in a Utc+N hours timezone.

This appears to fix the issue, but I'm surprised I'm the only one having this problem.

diff --git a/src/ADBSync/FileSystems/Android.py b/src/ADBSync/FileSystems/Android.py
index 142e6f3..d7aad87 100644
--- a/src/ADBSync/FileSystems/Android.py
+++ b/src/ADBSync/FileSystems/Android.py
@@ -190,8 +190,8 @@ class AndroidFileSystem(FileSystem):
                 yield self.ls_to_stat(line)
 
     def utime(self, path: str, times: Tuple[int, int]) -> None:
-        atime = datetime.datetime.utcfromtimestamp(times[0]).strftime("%Y%m%d%H%M")
-        mtime = datetime.datetime.utcfromtimestamp(times[1]).strftime("%Y%m%d%H%M")
+        atime = datetime.datetime.fromtimestamp(times[0]).strftime("%Y%m%d%H%M")
+        mtime = datetime.datetime.fromtimestamp(times[1]).strftime("%Y%m%d%H%M")
         for line in self.adb_shell(["touch", "-at", atime, "-mt", mtime, self.escape_path(path)]):
             self.line_not_captured(line)

weird behavior, synced files not showing up in gallery/other apps without copying manually once

[Android 13, mostly Stock (ASUS)]
I was getting a lot of random copying-stop errors in large manual file transfers (~8GB of photos/videos) so I used this tool.
It worked wonderfully, not just faster but without any errors.
However, I noticed that in my gallery, I could only see the files that I had manually copied, although in file explorers, I could confirm the files were there, taking the required space.
I tried copying over other small folders and noticed the same result - only files copied manually would show up in any gallery apps (stock and third party), so something is definitely missing

Does android do some media files db stuff when files are manually copied over, which might be missing in this tool?
Maybe these might be related: SO Link1
SO Link2

Any better fixes in the meantime?

Delete to recycle bin

When adding the --del flag on pulling, it permanently deletes files. Deleting to recycle bin would be good.

Broken symlink causes abort

Some of my /data/data/ files contained broken symlinks and caused your phenomenal script to abort
Easy to reproduce, create a symlink that points to a non-existent folder/file and try to sync it.

temporary workaround is: adb shell find -L /YOURPATHHERE -type l -exec rm -i {} \;

With -L, find tries to follow symbolic links to evaluate the -type test. If it succeeds in following the link, then the link is not broken, and the -type l test will be false (as it is evaluated for the thing that the link resolves to). If it fails in following the link, then the link is broken and the -type l test will be true.

If the -type l test succeeds, then the -exec rm {} \; removes the broken link.
source

Force to continue on permission denied error

Hello,

this is somewhat linked to #15, but not completely. I face the following error:

adbsync.py --del --show-progress pull /storage/emulated/0 /backup/primary/
ADB line not captured
ls: /storage/emulated/0/Android/data/org.videolan.vlc/files/medialib: Permission denied
Exiting

and I would like to have an option to still continue.

What I already tried is to create a regex for this error and raise a PermissionError, however, I was unable how to figure out how to just skip affected files...

diff --git a/src/ADBSync/FileSystems/Android.py b/src/ADBSync/FileSystems/Android.py
index a74acb9..a8e8565 100644
--- a/src/ADBSync/FileSystems/Android.py
+++ b/src/ADBSync/FileSystems/Android.py
@@ -52,6 +52,7 @@ class AndroidFileSystem(FileSystem):
         $""", re.DOTALL | re.VERBOSE)

     RE_NO_SUCH_FILE = re.compile("^.*: No such file or directory$")
+    RE_PERMISSION_DENIED = re.compile("^.*: Permission denied$")
     RE_LS_NOT_A_DIRECTORY = re.compile("ls: .*: Not a directory$")
     RE_TOTAL = re.compile("^total \\d+$")

@@ -118,7 +119,9 @@ class AndroidFileSystem(FileSystem):
             raise BrokenPipeError

     def ls_to_stat(self, line: str) -> Tuple[str, os.stat_result]:
-        if self.RE_NO_SUCH_FILE.fullmatch(line):
+        if self.RE_PERMISSION_DENIED.fullmatch(line):
+            raise PermissionError
+        elif self.RE_NO_SUCH_FILE.fullmatch(line):
             raise FileNotFoundError
         elif self.RE_LS_NOT_A_DIRECTORY.fullmatch(line):
             raise NotADirectoryError

Ideal would be an option to just ignore such errors and still sync the rest.

Thanks
Sebastian

BrokenPipeError: [Errno 32] Broken pipe

Hi,

I am trying to pull my full /sdcard from my Pixel phone to my Mac using the following command:

$ adb-sync -n --del --delete-excluded --pull '/Volumes/Macintosh HD/Users/username/sdcard' /sdcard

But I get the following error (I tried without -n and the result is the same):

Traceback (most recent call last):
  File "/Users/thomas/bin/adb-sync", line 6, in <module>
    ADBSync.main()
  File "/Users/thomas/code/better-adb-sync/src/ADBSync/__init__.py", line 358, in main
    path_source, path_destination = FileSyncer.paths_to_fixed_destination_paths(path_source, fs_source, path_destination, fs_destination)
  File "/Users/thomas/code/better-adb-sync/src/ADBSync/__init__.py", line 308, in paths_to_fixed_destination_paths
    lstat_source = fs_source.lstat(path_source)
  File "/Users/thomas/code/better-adb-sync/src/ADBSync/FileSystems/Android.py", line 182, in lstat
    for line in self.adb_shell(["ls", "-lad", self.escape_path(path)]):
  File "/Users/thomas/code/better-adb-sync/src/ADBSync/FileSystems/Android.py", line 89, in adb_shell
    self.proc_adb_shell.stdin.flush()
BrokenPipeError: [Errno 32] Broken pipe
Exception ignored in: <function AndroidFileSystem.__del__ at 0x7f89504d8e50>
Traceback (most recent call last):
  File "/Users/thomas/code/better-adb-sync/src/ADBSync/FileSystems/Android.py", line 82, in __del__
    self.proc_adb_shell.stdin.close()
BrokenPipeError: [Errno 32] Broken pipe

Any suggestion?

Cheers,

Tom

--reverse flag absent

The README mentions using --reverse to sync from the android device to the local device, but this flag isn't present in the code.

Non-zero exit code from adb push (SAOLogging.py:63)

[2023-07-03 17:09:01][CRITICAL] Non-zero exit code from adb push (SAOLogging.py:63)
[2023-07-03 17:09:01][DEBUG] Stack Trace (SAOLogging.py:64)
Stack (most recent call last):
  File "/Users/wzq/Applications/better-adb-sync/src/adbsync.py", line 6, in <module>
    ADBSync.main()
  File "/Users/wzq/Applications/better-adb-sync/src/ADBSync/__init__.py", line 510, in main
    fs_destination.push_tree_here(
  File "/Users/wzq/Applications/better-adb-sync/src/ADBSync/FileSystems/Base.py", line 91, in push_tree_here
    self.push_tree_here(
  File "/Users/wzq/Applications/better-adb-sync/src/ADBSync/FileSystems/Base.py", line 80, in push_tree_here
    self.push_file_here(tree_path, destination_root, show_progress = show_progress)
  File "/Users/wzq/Applications/better-adb-sync/src/ADBSync/FileSystems/Android.py", line 219, in push_file_here
    logging_fatal("Non-zero exit code from adb push")
  File "/Users/wzq/Applications/better-adb-sync/src/ADBSync/SAOLogging.py", line 64, in logging_fatal
    logging.debug("Stack Trace", stack_info = log_stack_info)
[2023-07-03 17:09:01][CRITICAL] Exiting (SAOLogging.py:65)

Can't get --exclude to work with --pull

I'm trying to copy the entire contents of /sdcard from a device to a computer while excluding certain large directories (such as the Spotify cache). But I can't seem to get the --exclude flag to work correctly.

I've tried:

adbsync.py -L --exclude "/sdcard/Android/data/com.spotify.music/" --pull . /sdcard/
adbsync.py -L --exclude "/sdcard/Android/data/com.spotify.music/*" --pull . /sdcard/

But both commands result in the excluded directories being copied:

/sdcard/Android/data/com.spotify.music/files/spotifycache/Storage/6f...88e574ac209a58b.file: 1 file pulled. 2.1 MB/s (3601 bytes in 0.002s)
/sdcard/Android/data/com.spotify.music/files/spotifycache/Storage/6f...a205583bf104.file: 1 file pulled. 19.4 MB/s (101635 bytes in 0.005s)
/sdcard/Android/data/com.spotify.music/files/spotifycache/Storage/6f...f36ae173de05.file: 1 file pulled. 25.4 MB/s (164866 bytes in 0.006s)

Am I using the flag incorrectly? It would be great to have some example usage for each of the flags in the README and when you run the script with no arguments.

exfat path normalisation results in deleting/recopying paths with trailing dots

Hi there!

Most modern Android devices use exfat/sdfat on the backing device. These filesystems strip trailing dots on path components as stripped as part of path resolution.

% dd if=/dev/zero of=exfat bs=100M count=10
10+0 records in
10+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 0.313496 s, 3.3 GB/s
% sudo losetup -fP exfat
% losetup -a
/dev/loop0: []: (/tmp/exfat)
% mkfs.exfat exfat
exfatprogs version : 1.1.3
Creating exFAT filesystem(exfat, cluster size=32768)

Writing volume boot record: done
Writing backup volume boot record: done
Fat table creation: done
Allocation bitmap creation: done
Upcase table creation: done
Writing root directory entry: done
Synchronizing...

exFAT format complete!
% mkdir test
% sudo mount -o loop /dev/loop0 test
% sudo mkdir test/...t.../
% sudo touch test/...t.../...e...
% sudo ls -la test/...t.../...e...
-rwxr-xr-x 1 root root 0 Sep  7 14:28 test/...t.../...e...
% sudo ls -la test/...t.../...e..
-rwxr-xr-x 1 root root 0 Sep  7 14:28 test/...t.../...e..
% sudo ls -la test/...t.../...e.
-rwxr-xr-x 1 root root 0 Sep  7 14:28 test/...t.../...e.
% sudo ls -la test/...t../...e.
-rwxr-xr-x 1 root root 0 Sep  7 14:28 test/...t../...e.

This results in deleting the old files, and then copying them again, even though they are the same:

[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/01 Stop.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/02 Malaise.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/03 Low Concept_High Maintenance.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/04 Nonsanity 2037x.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/05 Mr. Prince.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/06 Even the Scars Forget the Wounds.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/07 Go.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/08 Filling in a City.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/09 Destination.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/10 Mobile.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/11 Aggression.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/12 Then Silence.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/13 Stop and Go All Ye Faithful.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam/14 Graduated.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing folder /storage/21D1-F045/Music/Grüvis Malt/...With the Spirit of a Traffic Jam (Base.py:57)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Themselves/the no music/01 Home Work.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Themselves/the no music/02 Mouthful.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Themselves/the no music/03 Good People Check.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Themselves/the no music/04 Poisonpit.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Themselves/the no music/05 Live Trap.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Themselves/the no music/06 Only Child Explosion.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Themselves/the no music/07 Paging Dr. Moon Or Gun.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Themselves/the no music/08 Dark Sky Demo.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Themselves/the no music/09 You Devil You.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Themselves/the no music/10 Out In The Open.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing /storage/21D1-F045/Music/Themselves/the no music/11 Hat In The Wind.mp3 (Base.py:49)
[2022-09-07 13:50:05][INFO] Removing folder /storage/21D1-F045/Music/Themselves/the no music (Base.py:57)

[...]

[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../ (Base.py:85)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../01 Stop.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../02 Malaise.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../03 Low Concept_High Maintenance.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../04 Nonsanity 2037x.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../05 Mr. Prince.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../06 Even the Scars Forget the Wounds.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../07 Go.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../08 Filling in a City.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../09 Destination.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../10 Mobile.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../11 Aggression.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../12 Then Silence.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../13 Stop and Go All Ye Faithful.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Grüvis Malt/...With the Spirit of a Traffic Jam.../14 Graduated.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Themselves/the no music./ (Base.py:85)
[2022-09-07 13:50:05][INFO] ./Themselves/the no music./01 Home Work.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Themselves/the no music./02 Mouthful.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Themselves/the no music./03 Good People Check.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Themselves/the no music./04 Poisonpit.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Themselves/the no music./05 Live Trap.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Themselves/the no music./06 Only Child Explosion.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Themselves/the no music./07 Paging Dr. Moon Or Gun.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Themselves/the no music./08 Dark Sky Demo.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Themselves/the no music./09 You Devil You.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Themselves/the no music./10 Out In The Open.mp3 (Base.py:75)
[2022-09-07 13:50:05][INFO] ./Themselves/the no music./11 Hat In The Wind.mp3 (Base.py:75)

See __exfat_resolve_path for normalisation rules. Specifically, we should compare after stripping all trailing periods on these filesystems.

The harder parts are detecting if we're on exfat/sdfat in the first place with different phones having fastly different FUSE/DM topologies. Probably the strategy should be something like:

  1. Build a map of major:minor to whether this is an exfat-like mount stripping dots;
  2. On Android side, store major:minor for each path;
  3. Check if the path is on an exfat-like mount, and if so do custom equality check between local <-> android.

I'd usually just send out a patch, but I'm about to head out on holiday, so wanted to write this up first :-) I can take a look in a couple of weeks.

Thoughts and feedback on the idea appreciated, of course.

Thanks!

cannot carry on sync after stopping

syncing music library using command
python3 adbsync.py -v push ~/converted_music/ /sdcard/Music/converted
get this error

UnicodeDecodeError                        Traceback (most recent call last)
File ~/Documents/better-adb-sync-master/src/adbsync.py:6
      3 import ADBSync
      5 if __name__ == "__main__":
----> 6     ADBSync.main()

File ~/Documents/better-adb-sync-master/src/ADBSync/__init__.py:379, in main()
    376     perror(path_source, e, FATAL)
    378 try:
--> 379     files_tree_destination = fs_destination.get_files_tree(path_destination, follow_links = args.copy_links)
    380 except FileNotFoundError:
    381     files_tree_destination = None

File ~/Documents/better-adb-sync-master/src/ADBSync/FileSystems/Base.py:45, in FileSystem.get_files_tree(self, tree_path, follow_links)
     43 def get_files_tree(self, tree_path: str, follow_links: bool = False):
     44     statObject = self.lstat(tree_path)
---> 45     return self._get_files_tree(tree_path, statObject, follow_links = follow_links)

File ~/Documents/better-adb-sync-master/src/ADBSync/FileSystems/Base.py:33, in FileSystem._get_files_tree(self, tree_path, tree_path_stat, follow_links)
     31         if filename in [".", ".."]:
     32             continue
---> 33         tree[filename] = self._get_files_tree(
     34             self.join(tree_path, filename),
     35             stat_object_child,
     36             follow_links = follow_links)
     37     return tree
     38 elif stat.S_ISREG(tree_path_stat.st_mode):

File ~/Documents/better-adb-sync-master/src/ADBSync/FileSystems/Base.py:33, in FileSystem._get_files_tree(self, tree_path, tree_path_stat, follow_links)
     31         if filename in [".", ".."]:
     32             continue
---> 33         tree[filename] = self._get_files_tree(
     34             self.join(tree_path, filename),
     35             stat_object_child,
     36             follow_links = follow_links)
     37     return tree
     38 elif stat.S_ISREG(tree_path_stat.st_mode):

File ~/Documents/better-adb-sync-master/src/ADBSync/FileSystems/Base.py:30, in FileSystem._get_files_tree(self, tree_path, tree_path_stat, follow_links)
     28 elif stat.S_ISDIR(tree_path_stat.st_mode):
     29     tree = {".": (60 * (int(tree_path_stat.st_atime) // 60), 60 * (int(tree_path_stat.st_mtime) // 60))}
---> 30     for filename, stat_object_child, in self.lstat_in_dir(tree_path):
     31         if filename in [".", ".."]:
     32             continue

File ~/Documents/better-adb-sync-master/src/ADBSync/FileSystems/Android.py:188, in AndroidFileSystem.lstat_in_dir(self, path)
    187 def lstat_in_dir(self, path: str) -> Iterable[Tuple[str, os.stat_result]]:
--> 188     for line in self.adb_shell(["ls", "-la", self.escape_path(path)]):
    189         if self.RE_TOTAL.fullmatch(line):
    190             continue

File ~/Documents/better-adb-sync-master/src/ADBSync/FileSystems/Android.py:94, in AndroidFileSystem.adb_shell(self, commands)
     92 lines_to_yield: List[str] = []
     93 while adb_line := self.proc_adb_shell.stdout.readline():
---> 94     adb_line = adb_line.decode(self.adb_encoding).rstrip("\r\n")
     95     if adb_line == self.ADBSYNC_END_OF_COMMAND:
     96         break

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 67: invalid start byte

[Question] Preserving file timestamps?

Does the script consider timestamps of the files transfered? Meaning last time modified and creation time? Comparing to the original adb-sync there's no option for this (-t)

Improper handling of filenames (`;` and `:`)

Hi!

The tool fails to properly handle pass paths to adb when these contains ; or :.
I saw this happen both with directory names and with file names.

I believe it's related to #30

The stacktrace is the following (where REDACTED is a path component terminating with a :, but the full file name is longer).

[2023-09-08 11:43:44][CRITICAL] ADB line not captured (Android.py:103)                                                                                                                                             
[2023-09-08 11:43:44][CRITICAL] rm: /storage/emulated/0/REDACTED No such file or directory (SAOLogging.py:63)        
[2023-09-08 11:43:44][DEBUG] Stack Trace (SAOLogging.py:64)                                                                                                                                                        
Stack (most recent call last):                                                                                                                                                                                     
  File "/usr/bin/adbsync", line 8, in <module>                                                                                                                                                                     
    sys.exit(main())                                                                                     
  File "/usr/lib/python3.11/site-packages/BetterADBSync/__init__.py", line 503, in main                                                                                                                            
    fs_destination.remove_tree(path_destination, tree_unaccounted_destination_non_excluded, dry_run = args.dry_run)
  File "/usr/lib/python3.11/site-packages/BetterADBSync/FileSystems/Base.py", line 55, in remove_tree    
    self.remove_tree(self.normpath(self.join(tree_path, key)), value, dry_run = dry_run)                 
  File "/usr/lib/python3.11/site-packages/BetterADBSync/FileSystems/Base.py", line 55, in remove_tree    
    self.remove_tree(self.normpath(self.join(tree_path, key)), value, dry_run = dry_run)                                                                                                                           
  File "/usr/lib/python3.11/site-packages/BetterADBSync/FileSystems/Base.py", line 55, in remove_tree    
    self.remove_tree(self.normpath(self.join(tree_path, key)), value, dry_run = dry_run)
  [Previous line repeated 1 more time]                                                                   
  File "/usr/lib/python3.11/site-packages/BetterADBSync/FileSystems/Base.py", line 51, in remove_tree
    self.unlink(tree_path)    
  File "/usr/lib/python3.11/site-packages/BetterADBSync/FileSystems/Android.py", line 163, in unlink
    self.line_not_captured(line)                                                                         
  File "/usr/lib/python3.11/site-packages/BetterADBSync/FileSystems/Android.py", line 104, in line_not_captured
    logging_fatal(line)               
  File "/usr/lib/python3.11/site-packages/BetterADBSync/SAOLogging.py", line 64, in logging_fatal
    logging.debug("Stack Trace", stack_info = log_stack_info)
[2023-09-08 11:43:44][CRITICAL] Exiting (SAOLogging.py:65)

[Feature request] Add skip errors option

Feature request:

Add skip error option.
If for whatever reason file cannot be copied, it should be ignored and rest of the copy / pull should proceed.

At the end there could be a list of failed files for review.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.