mirror of
https://github.com/google/adb-sync.git
synced 2026-01-03 09:58:01 +00:00
Fix lint, and make logging actually work again.
This commit is contained in:
126
adb-sync
126
adb-sync
@@ -17,14 +17,12 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import argparse
|
import argparse
|
||||||
import glob
|
|
||||||
import locale
|
import locale
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import stat
|
import stat
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Callable, cast, Dict, List, IO, Iterable, Optional, Tuple, Type
|
from typing import Callable, cast, Dict, List, IO, Iterable, Optional, Tuple, Type
|
||||||
@@ -32,25 +30,28 @@ from typing import Callable, cast, Dict, List, IO, Iterable, Optional, Tuple, Ty
|
|||||||
|
|
||||||
class OSLike(object):
|
class OSLike(object):
|
||||||
|
|
||||||
def listdir(self, path: bytes) -> Iterable[bytes]:
|
def listdir(self, path: bytes) -> Iterable[bytes]: # os's name, so pylint: disable=g-bad-name
|
||||||
raise NotImplementedError('Abstract')
|
raise NotImplementedError('Abstract')
|
||||||
|
|
||||||
def lstat(self, path: bytes) -> os.stat_result:
|
def lstat(self, path: bytes) -> os.stat_result: # os's name, so pylint: disable=g-bad-name
|
||||||
raise NotImplementedError('Abstract')
|
raise NotImplementedError('Abstract')
|
||||||
|
|
||||||
def unlink(self, path: bytes) -> None:
|
def unlink(self, path: bytes) -> None: # os's name, so pylint: disable=g-bad-name
|
||||||
raise NotImplementedError('Abstract')
|
raise NotImplementedError('Abstract')
|
||||||
|
|
||||||
def rmdir(self, path: bytes) -> None:
|
def rmdir(self, path: bytes) -> None: # os's name, so pylint: disable=g-bad-name
|
||||||
raise NotImplementedError('Abstract')
|
raise NotImplementedError('Abstract')
|
||||||
|
|
||||||
def makedirs(self, path: bytes) -> None:
|
def makedirs(self, path: bytes) -> None: # os's name, so pylint: disable=g-bad-name
|
||||||
raise NotImplementedError('Abstract')
|
raise NotImplementedError('Abstract')
|
||||||
|
|
||||||
def utime(self, path: bytes, times: Tuple[float, float]) -> None:
|
def utime(self, path: bytes, times: Tuple[float, float]) -> None: # os's name, so pylint: disable=g-bad-name
|
||||||
raise NotImplementedError('Abstract')
|
raise NotImplementedError('Abstract')
|
||||||
|
|
||||||
def glob(self, path: bytes) -> Iterable[bytes]:
|
|
||||||
|
class GlobLike(object):
|
||||||
|
|
||||||
|
def glob(self, path: bytes) -> Iterable[bytes]: # glob's name, so pylint: disable=g-bad-name
|
||||||
raise NotImplementedError('Abstract')
|
raise NotImplementedError('Abstract')
|
||||||
|
|
||||||
|
|
||||||
@@ -83,7 +84,7 @@ class Stdout(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class AdbFileSystem(OSLike):
|
class AdbFileSystem(GlobLike, OSLike):
|
||||||
"""Mimics os's file interface but uses the adb utility."""
|
"""Mimics os's file interface but uses the adb utility."""
|
||||||
|
|
||||||
def __init__(self, adb: List[bytes]) -> None:
|
def __init__(self, adb: List[bytes]) -> None:
|
||||||
@@ -118,16 +119,16 @@ class AdbFileSystem(OSLike):
|
|||||||
[ ]+
|
[ ]+
|
||||||
[^ ]+ # Group name/ID.
|
[^ ]+ # Group name/ID.
|
||||||
[ ]+
|
[ ]+
|
||||||
(?(S_IFBLK) [^ ]+[ ]+[^ ]+[ ]+) # Device numbers.
|
(?(S_IFBLK) [^ ]+[ ]+[^ ]+[ ]+) # Device numbers.
|
||||||
(?(S_IFCHR) [^ ]+[ ]+[^ ]+[ ]+) # Device numbers.
|
(?(S_IFCHR) [^ ]+[ ]+[^ ]+[ ]+) # Device numbers.
|
||||||
(?(S_IFDIR) [0-9]+ [ ]+)? # directory Size.
|
(?(S_IFDIR) [0-9]+ [ ]+)? # directory Size.
|
||||||
(?(S_IFREG)
|
(?(S_IFREG)
|
||||||
(?P<st_size> [0-9]+) # Size.
|
(?P<st_size> [0-9]+) # Size.
|
||||||
[ ]+)
|
[ ]+)
|
||||||
(?P<st_mtime>
|
(?P<st_mtime>
|
||||||
[0-9]{4}-[0-9]{2}-[0-9]{2} # Date.
|
[0-9]{4}-[0-9]{2}-[0-9]{2} # Date.
|
||||||
[ ]
|
[ ]
|
||||||
[0-9]{2}:[0-9]{2}) # Time.
|
[0-9]{2}:[0-9]{2}) # Time.
|
||||||
[ ]
|
[ ]
|
||||||
# Don't capture filename for symlinks (ambiguous).
|
# Don't capture filename for symlinks (ambiguous).
|
||||||
(?(S_IFLNK) .* | (?P<filename> .*))
|
(?(S_IFLNK) .* | (?P<filename> .*))
|
||||||
@@ -253,7 +254,7 @@ class AdbFileSystem(OSLike):
|
|||||||
if line.startswith(b'total '):
|
if line.startswith(b'total '):
|
||||||
continue
|
continue
|
||||||
line = line.rstrip(b'\r\n')
|
line = line.rstrip(b'\r\n')
|
||||||
statdata, filename = self.LsToStat(line)
|
statdata, _ = self.LsToStat(line)
|
||||||
self.stat_cache[path] = statdata
|
self.stat_cache[path] = statdata
|
||||||
return statdata
|
return statdata
|
||||||
raise OSError('No such file or directory')
|
raise OSError('No such file or directory')
|
||||||
@@ -297,7 +298,7 @@ class AdbFileSystem(OSLike):
|
|||||||
b'touch -at %s %s' % (timestr, self.QuoteArgument(path))]) != 0:
|
b'touch -at %s %s' % (timestr, self.QuoteArgument(path))]) != 0:
|
||||||
raise OSError('touch failed')
|
raise OSError('touch failed')
|
||||||
|
|
||||||
def glob(self, path: bytes) -> Iterable[bytes]:
|
def glob(self, path: bytes) -> Iterable[bytes]: # glob's name, so pylint: disable=g-bad-name
|
||||||
with Stdout(
|
with Stdout(
|
||||||
self.adb +
|
self.adb +
|
||||||
[b'shell', b'for p in %s; do echo "$p"; done' % (path,)]) as stdout:
|
[b'shell', b'for p in %s; do echo "$p"; done' % (path,)]) as stdout:
|
||||||
@@ -626,7 +627,7 @@ class FileSyncer(object):
|
|||||||
dt)
|
dt)
|
||||||
|
|
||||||
|
|
||||||
def ExpandWildcards(globber: OSLike, path: bytes) -> Iterable[bytes]:
|
def ExpandWildcards(globber: GlobLike, path: bytes) -> Iterable[bytes]:
|
||||||
if path.find(b'?') == -1 and path.find(b'*') == -1 and path.find(b'[') == -1:
|
if path.find(b'?') == -1 and path.find(b'*') == -1 and path.find(b'[') == -1:
|
||||||
return [path]
|
return [path]
|
||||||
return globber.glob(path)
|
return globber.glob(path)
|
||||||
@@ -654,25 +655,27 @@ def FixPath(src: bytes, dst: bytes) -> Tuple[bytes, bytes]:
|
|||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description='Synchronize a directory between an Android device and the ' +
|
description='Synchronize a directory between an Android device and the '
|
||||||
'local file system')
|
'local file system')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'source',
|
'source',
|
||||||
metavar='SRC',
|
metavar='SRC',
|
||||||
type=str,
|
type=str,
|
||||||
nargs='+',
|
nargs='+',
|
||||||
help='The directory to read files/directories from. ' +
|
help='The directory to read files/directories from. '
|
||||||
'This must be a local path if -R is not specified, ' +
|
'This must be a local path if -R is not specified, '
|
||||||
'and an Android path if -R is specified. If SRC does ' +
|
'and an Android path if -R is specified. If SRC does '
|
||||||
'not end with a final slash, its last path component ' +
|
'not end with a final slash, its last path component '
|
||||||
'is appended to DST (like rsync does).')
|
'is appended to DST (like rsync does).')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'destination',
|
'destination',
|
||||||
metavar='DST',
|
metavar='DST',
|
||||||
type=str,
|
type=str,
|
||||||
help='The directory to write files/directories to. ' +
|
help='The directory to write files/directories to. '
|
||||||
'This must be an Android path if -R is not specified, ' +
|
'This must be an Android path if -R is not specified, '
|
||||||
'and a local path if -R is specified.')
|
'and a local path if -R is specified.')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-e',
|
'-e',
|
||||||
@@ -684,38 +687,38 @@ def main() -> None:
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--device',
|
'--device',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Directs command to the only connected USB device; ' +
|
help='Directs command to the only connected USB device; '
|
||||||
'returns an error if more than one USB device is ' + 'present. ' +
|
'returns an error if more than one USB device is present. '
|
||||||
'Corresponds to the "-d" option of adb.')
|
'Corresponds to the "-d" option of adb.')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--emulator',
|
'--emulator',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Directs command to the only running emulator; ' +
|
help='Directs command to the only running emulator; '
|
||||||
'returns an error if more than one emulator is running. ' +
|
'returns an error if more than one emulator is running. '
|
||||||
'Corresponds to the "-e" option of adb.')
|
'Corresponds to the "-e" option of adb.')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-s',
|
'-s',
|
||||||
'--serial',
|
'--serial',
|
||||||
metavar='DEVICE',
|
metavar='DEVICE',
|
||||||
type=str,
|
type=str,
|
||||||
help='Directs command to the device or emulator with ' +
|
help='Directs command to the device or emulator with '
|
||||||
'the given serial number or qualifier. Overrides ' +
|
'the given serial number or qualifier. Overrides '
|
||||||
'ANDROID_SERIAL environment variable. Use "adb devices" ' +
|
'ANDROID_SERIAL environment variable. Use "adb devices" '
|
||||||
'to list all connected devices with their respective ' + 'serial number. '
|
'to list all connected devices with their respective serial number. '
|
||||||
+ 'Corresponds to the "-s" option of adb.')
|
'Corresponds to the "-s" option of adb.')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-H',
|
'-H',
|
||||||
'--host',
|
'--host',
|
||||||
metavar='HOST',
|
metavar='HOST',
|
||||||
type=str,
|
type=str,
|
||||||
help='Name of adb server host (default: localhost). ' +
|
help='Name of adb server host (default: localhost). '
|
||||||
'Corresponds to the "-H" option of adb.')
|
'Corresponds to the "-H" option of adb.')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-P',
|
'-P',
|
||||||
'--port',
|
'--port',
|
||||||
metavar='PORT',
|
metavar='PORT',
|
||||||
type=str,
|
type=str,
|
||||||
help='Port of adb server (default: 5037). ' +
|
help='Port of adb server (default: 5037). '
|
||||||
'Corresponds to the "-P" option of adb.')
|
'Corresponds to the "-P" option of adb.')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-R',
|
'-R',
|
||||||
@@ -726,54 +729,57 @@ def main() -> None:
|
|||||||
'-2',
|
'-2',
|
||||||
'--two-way',
|
'--two-way',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Two-way sync (compare modification time; after ' +
|
help='Two-way sync (compare modification time; after '
|
||||||
'the sync, both sides will have all files in the ' +
|
'the sync, both sides will have all files in the '
|
||||||
'respective newest version. This relies on the clocks ' +
|
'respective newest version. This relies on the clocks '
|
||||||
'of your system and the device to match.')
|
'of your system and the device to match.')
|
||||||
#parser.add_argument('-t', '--times', action='store_true',
|
parser.add_argument(
|
||||||
# help='Preserve modification times when copying.')
|
'-t',
|
||||||
|
'--times',
|
||||||
|
action='store_true',
|
||||||
|
help='Preserve modification times when copying.')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-d',
|
'-d',
|
||||||
'--delete',
|
'--delete',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Delete files from DST that are not present on ' +
|
help='Delete files from DST that are not present on '
|
||||||
'SRC. Mutually exclusive with -2.')
|
'SRC. Mutually exclusive with -2.')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-f',
|
'-f',
|
||||||
'--force',
|
'--force',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Allow deleting files/directories when having to ' +
|
help='Allow deleting files/directories when having to '
|
||||||
'replace a file by a directory or vice versa. This is ' +
|
'replace a file by a directory or vice versa. This is '
|
||||||
'disabled by default to prevent large scale accidents.')
|
'disabled by default to prevent large scale accidents.')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-n',
|
'-n',
|
||||||
'--no-clobber',
|
'--no-clobber',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Do not ever overwrite any ' +
|
help='Do not ever overwrite any '
|
||||||
'existing files. Mutually exclusive with -f.')
|
'existing files. Mutually exclusive with -f.')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--dry-run',
|
'--dry-run',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Do not do anything - just show what would ' + 'be done.')
|
help='Do not do anything - just show what would be done.')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
args_encoding = locale.getdefaultlocale()[1]
|
args_encoding = locale.getdefaultlocale()[1] or 'ascii'
|
||||||
|
|
||||||
localpatterns = [x.encode(args_encoding) for x in args.source]
|
localpatterns = [x.encode(args_encoding) for x in args.source]
|
||||||
remotepath = args.destination.encode(args_encoding)
|
remotepath = args.destination.encode(args_encoding)
|
||||||
adb = args.adb.encode(args_encoding).split(b' ')
|
adb_args = args.adb.encode(args_encoding).split(b' ')
|
||||||
if args.device:
|
if args.device:
|
||||||
adb += [b'-d']
|
adb_args += [b'-d']
|
||||||
if args.emulator:
|
if args.emulator:
|
||||||
adb += [b'-e']
|
adb_args += [b'-e']
|
||||||
if args.serial != None:
|
if args.serial:
|
||||||
adb += [b'-s', args.serial.encode(args_encoding)]
|
adb_args += [b'-s', args.serial.encode(args_encoding)]
|
||||||
if args.host != None:
|
if args.host:
|
||||||
adb += [b'-H', args.host.encode(args_encoding)]
|
adb_args += [b'-H', args.host.encode(args_encoding)]
|
||||||
if args.port != None:
|
if args.port:
|
||||||
adb += [b'-P', args.port.encode(args_encoding)]
|
adb_args += [b'-P', args.port.encode(args_encoding)]
|
||||||
adb = AdbFileSystem(adb)
|
adb = AdbFileSystem(adb_args)
|
||||||
|
|
||||||
# Expand wildcards.
|
# Expand wildcards, but only on the remote side.
|
||||||
localpaths = []
|
localpaths = []
|
||||||
remotepaths = []
|
remotepaths = []
|
||||||
if args.reverse:
|
if args.reverse:
|
||||||
@@ -788,7 +794,7 @@ def main() -> None:
|
|||||||
localpaths.append(src)
|
localpaths.append(src)
|
||||||
remotepaths.append(dst)
|
remotepaths.append(dst)
|
||||||
|
|
||||||
preserve_times = False # args.times
|
preserve_times = args.times
|
||||||
delete_missing = args.delete
|
delete_missing = args.delete
|
||||||
allow_replace = args.force
|
allow_replace = args.force
|
||||||
allow_overwrite = not args.no_clobber
|
allow_overwrite = not args.no_clobber
|
||||||
|
|||||||
Reference in New Issue
Block a user