File: android-deltas-sync/sync-changes-part2-phone.py

#!/data/data/com.termux/files/usr/bin/python3
#!/usr/bin/env python3  <= fails in Termux:Widget (see also _etc shims)
"""
=======================================================================
Sync Changes to Phone, Part 2: Phone

Run syncs whenever desired to propagate PC changes to the phone.  
The phone will be updated only for modifications made on the PC.

See _README.html for license, attribution, version, and docs.

-----------------------------------------------------------------------
Usage:

Run this on your phone second (after running Part 1 on your PC), with:

    python3 sync-changes-part2-phone.py

Run this from the Termux app's console, or any other app with a 
console terminal.  This file may also be run with no command line 
from a Python IDE app (e.g., Pydroid 3 or QPython), and/or a 
home-screen shortcut or widget (e.g., Termux:Widget).

Run this from any folder.  It uses paths set in config_phone.py,
and finds that and common.py in its own folder automatically.

Step runtimes are shown in the console after step completion.  
Step outputs go to files in LOGS; watch with 'tail -f LOGS/file'.

See _README.html for license, attribution, version, and docs.

-----------------------------------------------------------------------
Notes:

0) "PC" here means a Windows, macOS, or Linux device, but "phone" 
can be anything: though designed to sync changes to Android 11 and 
later, these scripts can also sync to earlier Androids and PCs.

1) Heritage: this is a Python translation of a same-named Bash 
script in folder _etc/bash-version/; hence the too-many globals.
Translated for Windows portability: Cygwin and WSL have seams.
The Bash originals more explicitly show command lines run here.
=======================================================================
"""

import os, sys, shutil
from os.path import join

import config_phone, common             # get phone settings and common code 
common.startup(config_phone, common)    # copy and use phone config's settings
from common import *                    # use both's top-level names as globals

# subjects
thezip = join(FROM, 'DELTAS.zip')       # where user copies zipfile on phone
thedlt = join(FROM, 'DELTAS')           # what the unzip creates on phone
thedst = join(TO,   STUFF)              # where deltas are applied on phone

# 'to' must exist here
if not os.path.isdir(thedst):
    print('The TO/STUFF folder does not exist: "%s"' % thedst)
    print('Exiting; please check the config file and rerun.')
    shutdown(bad=True)

opener('Syncing:\nfrom %s\nto   %s\nlogs %s' % (thezip, thedst, LOGS))


#----------------------------------------------------------------
# 1) Copy deltas zip from proxy to phone with an explorer app
#----------------------------------------------------------------

# Choose your app (but not Termux: POSIX cannot access USB in 11)

msg = """
Manually copy or move DELTAS.zip
    from the root of the USB drive
    to   %s
using any Android file-explorer app with suitable storage permissions.
""" % FROM

print(msg)
input('Press enter/return here when the copy is finished...')

# did the copy work?
if not os.path.exists(thezip):
    print('Deltas zip not found at "%s"' % thezip)
    print('Please rerun this script to try again.')
    shutdown(bad=True)


#----------------------------------------------------------------
# 2) Unzip deltas on phone with [zip-extract.py] in Termux
#----------------------------------------------------------------

announce('Unzipping deltas on phone')
logto = join(LOGS, '%s--sync-1-unzip-deltas-log.txt' % DATE)

# for a deltas tree not deleted by last run: delete, iff approved
removeExistingOrStop(thedlt, 'phone (DELTAS)')

# perms may disable updates in app-specific storage
permissions = ('-permissions',) if UnixPermissions else ()

runpy(join(ZIP, 'zip-extract.py'), 
      thezip, FROM, *permissions,            # makes FROM/DELTAS == thedlt
      logpath=logto,
      tailing=(1, 'Zip extract summary'))


#----------------------------------------------------------------
# 3) Apply deltas to phone with [mergeall.py -restore] in Termux
#----------------------------------------------------------------

announce('Applying deltas to phone')
logto = join(LOGS, '%s--sync-2-apply-deltas-log.txt' % DATE)

# backup phone changes? (__bkp__ prunes slow in shared storage)
backup = ('-backup',) if BackupChanges else ()

runpy(join(MALL, 'mergeall.py'),
      thedlt, thedst, '-restore', '-auto', '-skipcruft', *backup, '-quiet',
      logpath=logto,
      tailing=(9, 'Mergeall summary'))


#----------------------------------------------------------------
# 4) Cleanup deltas zip and folder on phone in Termux
#----------------------------------------------------------------

print('Removing deltas folder from phone')
timefunc(lambda: rmtree_FWP(thedlt, required=False))

# on-phone zip; user may have copied or moved the proxy zip, but can't check here

print('Removing deltas zip from phone (remove manually from proxy as needed)')
timefunc(lambda: os.remove(thezip)) 


#----------------------------------------------------------------
# Configurable: hook for custom post-propagate steps
#----------------------------------------------------------------

import z_postcopy_hook_phone    # no need for runpy() in __file__ here


closer('See logs in "%s".' % LOGS)



[Home page] Books Code Blog Python Author Train Find ©M.Lutz