File: android-deltas-sync/x-verify-phone-part2-pc.py

#!/usr/bin/env python3
"""
=======================================================================
Verify Phone Content, Part 2: PC    [new in 1.1]

Run verifications occasionally (if ever) to prove that the on-phone 
content copy matches that on the PC; it's a useful but slow process.

Verify scripts can also be used to export phone content to a PC,
but may require a manual proxy sync.  As of 1.2, the new x-export-* 
scripts perform fully-automated exports to both PC and proxy.

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

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

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

     python3 x-verify-phone-part2-pc.py

Run this in Terminal on macOS and Linux; and in Command Prompt,
PowerShell, Cygwin, or WSL on Windows.  Replace its "python3" 
with "python" where needed, and "py -3" in basic Windows shells.
This file may also be run with no command line by click or IDE.

Run this from any folder.  It uses paths set in config_pc.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'.

-----------------------------------------------------------------------
Exports:

*UPDATE*: as of 1.2, you can ignore the following note if you use 
the new x-export-* scripts to export phone content, instead of the 
x-verify-* scripts.  The export scripts update the proxy automatically
along with the PC.  The verify scripts (including this) are now 
officially intended for phone verifications only; any other usage
may require some manual intervention per the following.

*IMPORTANT*: this does not sync the _proxy_ to match the phone's
content, because that is not necessary for verification roles.  
In _export_ roles, if the phone's copy has been change directly,
you must also sync the proxy to match the phone's content copy 
exported to the PC, by running a manual Mergeall like this:

   $ python3 $MALL/mergeall.py pccopy proxycopy -auto -skipcruft -quiet

You could also make the proxy match the PC and phone by unzipping 
PHONE.zip onto the proxy, but it's likely slower; or by simply
running sync-changes-part1-pc.py, but it's overkill in this context.
See "Phone Exports" in _README.html for more on exporting to PC.
This use case is partly manual because it's a full copy, not a sync. 

-----------------------------------------------------------------------
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) You can run the unzip and mergeall/diffall steps here manually;
this script is simply a convenience that automates the steps and
follows the rest of this package's motif, with error/safety checks.

2) This uses the PC config's settings unchanged, but inverts 
their meaning: "FROM" (the on-PC copy) is what the phone zip's 
content is compared with, and "TO" (the proxy drive) is really 
FROM here (for the zip).  The phone zip is assumed to be at the 
root of the TO proxy drive.

3) Caveat: verification makes a full-content zipfile on the phone,
which is then moved to the proxy drive and unzipped on the PC.
Hence, you'll need _twice_ the size of full content on all three
devices.  This is unavoidable without on-phone POSIX USB access. 

4) This uses _uncompressed_ zips for speed; the space savings for 
compression is minimal, and won't help much with the preceding note.

5) This does _not_ move the phone-copy zip from proxy to PC, even 
though this may be faster than unzipping from the proxy, because
moving the zip to PC would raise the PC space requirement from 2X
to 3X full-content size - for both a content zip and content unzip.

6) As of 1.2, this was renamed from "verify..." to "x-verify..."
because it's a lesser and optional tool, and so that it appears at 
the end of by-name folder listings.  Exports are named similarly.
=======================================================================
"""

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

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

# subjects
TOroot = driveRootPath(TO)
prxzip = join(TOroot, 'PHONE.zip')    # where phone zip was put on proxy
tmpfld = join(FROM,   'PHONE')        # where phone zip is unzipped (temp)
tmpsrc = join(tmpfld, STUFF)          # where unzipped content is nested
thesrc = join(FROM,   STUFF)          # where content is on PC

# 'from' and 'to' must both exist here
if not os.path.isfile(prxzip):
    print('The TO/PHONE.zip file does not exist on the proxy: "%s"' % prxzip)
    print('Exiting; please check the config file and rerun.')
    shutdown(bad=True)

if not os.path.isdir(thesrc):
    print('The FROM/STUFF on-PC content folder does not exist: "%s"' % thesrc)
    print('Exiting; please check the config file and rerun.')
    shutdown(bad=True)

opener('Verifying:\nfrom %s\nto   %s\nlogs %s' % (prxzip, thesrc, LOGS))


#----------------------------------------------------------------
# 1) Unzip phone content on PC with [zip-extract.py] in console
#----------------------------------------------------------------

# Do not move zipfile from proxy to PC: faster, but need 3X space

# timefunc(lambda: moveZipToProxy(prxzip, tmpzip))   # argument roles reversed

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

# delete an existing temp content tree, iff approved
removeExistingOrStop(tmpfld, 'pc (temp unzip copy)')

# disables updates in app-specific storage on phone: likely moot here
permissions = ('-permissions',)

runpy(join(ZIP, 'zip-extract.py'), 
      prxzip, tmpfld, *permissions,             # makes tmpfld/STUFF == tmpsrc
      logpath=logto,
      tailing=(1, 'Zip extract summary'))


#----------------------------------------------------------------
# 2) Compare phone copy to PC copy: mergeall (fast) + diffall?
#----------------------------------------------------------------

# Nit: like common.verifyPCtoProxy(), but custom enough for copy 

announce('Running mergeall to verify phone content')
logto = join(LOGS, '%s--verify-2-mergeall-log.txt' % DATE)
runpy(join(MALL, 'mergeall.py'), 
      tmpsrc, thesrc, '-report', '-skipcruft', '-quiet',
      logpath=logto,
      tailing=(9, 'Mergeall summary'))

userreply = input('\nShow full Mergeall output (y or n)?')
if userreply == 'y':
    print(open(logto, 'r', encoding='utf8').read())

userreply = input('Verify phone content with diffall too (y or n)?')
if userreply == 'y':
    print('Running diffall to verify phone content')
    logto = join(LOGS, '%s--verify-3-diffall-log.txt' % DATE)
    runpy(join(MALL, 'diffall.py'),
          tmpsrc, thesrc, '-skipcruft', '-quiet',
          logpath=logto,
          tailing=(7, 'Diffall summary'))    # 6=none, 7=1 unique (__bkp__)

    userreply = input('\nShow full diffall output (y or n)?')
    if userreply == 'y':
        print(open(logto, 'r', encoding='utf8').read(), end='')


#----------------------------------------------------------------
# 3) Cleanup content zip on proxy, and content folder on PC
#----------------------------------------------------------------

# Ask first: may want to retain either/both if diffs to be analyzed

userreply = input("\nRemove verify's zipfile from proxy drive (y or n)?")
if userreply == 'y':
    timefunc(lambda: os.remove(prxzip))
else:
    print('Retained "%s"' % prxzip)

userreply = input("\nRemove verify's unzipped content folder from PC (y or n)?")
if userreply == 'y':
    timefunc(lambda: rmtree_FWP(tmpfld, required=False))
else:
    print('Retained "%s"' % tmpfld)


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



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