File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / support / git-set-file-times
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:32:36 2021 UTC (3 years, 3 months ago) by misho
Branches: rsync, MAIN
CVS tags: v3_2_3, HEAD
rsync 3.2.3

    1: #!/usr/bin/env python3
    2: 
    3: import os, re, argparse, subprocess
    4: from datetime import datetime
    5: 
    6: NULL_COMMIT_RE = re.compile(r'\0\0commit [a-f0-9]{40}$|\0$')
    7: 
    8: def main():
    9:     if not args.git_dir:
   10:         cmd = 'git rev-parse --show-toplevel 2>/dev/null || echo .'
   11:         top_dir = subprocess.check_output(cmd, shell=True, encoding='utf-8').strip()
   12:         args.git_dir = os.path.join(top_dir, '.git')
   13:         if not args.prefix:
   14:             os.chdir(top_dir)
   15: 
   16:     git = [ 'git', '--git-dir=' + args.git_dir ]
   17: 
   18:     if args.tree:
   19:         cmd = git + 'ls-tree -z -r --name-only'.split() + [ args.tree ]
   20:     else:
   21:         cmd = git + 'ls-files -z'.split()
   22: 
   23:     proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, encoding='utf-8')
   24:     out = proc.communicate()[0]
   25:     ls = set(out.split('\0'))
   26:     ls.discard('')
   27: 
   28:     if not args.tree:
   29:         # All modified files keep their current mtime.
   30:         proc = subprocess.Popen(git + 'ls-files -m -z'.split(), stdout=subprocess.PIPE, encoding='utf-8')
   31:         out = proc.communicate()[0]
   32:         for fn in out.split('\0'):
   33:             if fn == '':
   34:                 continue
   35:             if args.list:
   36:                 mtime = os.lstat(fn).st_mtime
   37:                 print_line(fn, mtime, mtime)
   38:             ls.discard(fn)
   39: 
   40:     cmd = git + 'log -r --name-only --no-color --pretty=raw --no-renames -z'.split()
   41:     if args.tree:
   42:         cmd.append(args.tree)
   43:     cmd += ['--'] + args.files
   44: 
   45:     proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, encoding='utf-8')
   46:     for line in proc.stdout:
   47:         line = line.strip()
   48:         m = re.match(r'^committer .*? (\d+) [-+]\d+$', line)
   49:         if m:
   50:             commit_time = int(m[1])
   51:         elif NULL_COMMIT_RE.search(line):
   52:             line = NULL_COMMIT_RE.sub('', line)
   53:             files = set(fn for fn in line.split('\0') if fn in ls)
   54:             if not files:
   55:                 continue
   56:             for fn in files:
   57:                 if args.prefix:
   58:                     fn = args.prefix + fn
   59:                 mtime = os.lstat(fn).st_mtime
   60:                 if args.list:
   61:                     print_line(fn, mtime, commit_time)
   62:                 elif mtime != commit_time:
   63:                     if not args.quiet:
   64:                         print(f"Setting {fn}")
   65:                     os.utime(fn, (commit_time, commit_time), follow_symlinks = False)
   66:             ls -= files
   67:             if not ls:
   68:                 break
   69:     proc.communicate()
   70: 
   71: 
   72: def print_line(fn, mtime, commit_time):
   73:     if args.list > 1:
   74:         ts = str(commit_time).rjust(10)
   75:     else:
   76:         ts = datetime.utcfromtimestamp(commit_time).strftime("%Y-%m-%d %H:%M:%S")
   77:     chg = '.' if mtime == commit_time else '*'
   78:     print(chg, ts, fn)
   79: 
   80: 
   81: if __name__ == '__main__':
   82:     parser = argparse.ArgumentParser(description="Set the times of the files in the current git checkout to their last-changed time.", add_help=False)
   83:     parser.add_argument('--git-dir', metavar='GIT_DIR', help="The git dir to query (defaults to affecting the current git checkout).")
   84:     parser.add_argument('--tree', metavar='TREE-ISH', help="The tree-ish to query (defaults to the current branch).")
   85:     parser.add_argument('--prefix', metavar='PREFIX_STR', help="Prepend the PREFIX_STR to each filename we tweak (defaults to the top of current checkout).")
   86:     parser.add_argument('--quiet', '-q', action='store_true', help="Don't output the changed-file information.")
   87:     parser.add_argument('--list', '-l', action='count', help="List files & times instead of changing them. Repeat for Unix timestamp instead of human readable.")
   88:     parser.add_argument('files', metavar='FILE', nargs='*', help="Specify a subset of checked-out files to tweak.")
   89:     parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
   90:     args = parser.parse_args()
   91:     main()
   92: 
   93: # vim: sw=4 et

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>