3 # Find commit date/time for every commit, list files in the commit
4 # and set the file's modification time to the date/time of the latest commit.
6 # Adapted from https://git.wiki.kernel.org/index.php/ExampleScripts#Setting_the_timestamps_of_the_files_to_the_commit_timestamp_of_the_commit_which_last_touched_them # noqa
13 git_root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'],
14 universal_newlines=True).rstrip('\n')
17 parser = argparse.ArgumentParser(description='Set commit date')
18 parser.add_argument('-a', '--author', '--author-date',
20 parser.add_argument('-c', '--committer', '--committer-date',
22 args = parser.parse_args()
24 if args.author and args.committer:
26 sys.exit("Use only one of `-a' or `-c' but not both")
31 date_format = 'c' # This is the default
33 separator = '----- GIT LOG SEPARATOR -----'
35 git_log = subprocess.Popen(['git', 'log', '-m', '--first-parent',
36 '--name-status', '--no-color',
37 '--format=%s%%n%%%st' % (separator, date_format)],
38 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
39 universal_newlines=True)
43 # stages: 1 - start of commit, 2 - timestamp, 3 - empty line, 4 - files
45 for line in git_log.stdout:
47 if (stage in (1, 4)) and (line == separator): # Start of a commit
53 if line == separator: # Null-merge (git merge -s ours), no files
57 assert line == '', line
59 if line.startswith('A') or line.startswith('M') \
60 or line.startswith('D'):
61 filename = line.split(None, 2)[1]
62 elif line.startswith('R'):
63 filename = line.split(None, 3)[2] # renamed to
64 if line.startswith('D') and filename not in changed_files:
65 # The file was not readded
66 deleted_files.add(filename)
67 if filename not in deleted_files and filename not in changed_files:
68 changed_files.add(filename)
69 if os.path.exists(filename) and not os.path.islink(filename):
70 os.utime(filename, (time, time))
72 raise ValueError("stage: %d, line: %s" % (stage, line))
75 git_log.stdout.close()