#!/usr/bin/env python3

"""
This is a simple program that will insert some regular file into the root
commit(s) of history, e.g. adding a file named LICENSE or COPYING to the
first commit.  It also rewrites commit hashes in commit messages to update
them based on these changes.
"""

"""
Please see the
  ***** API BACKWARD COMPATIBILITY CAVEAT *****
near the top of git-filter-repo.
"""

# Technically, this program could be replaced by a one-liner:
#    git filter-repo --commit-callback "if not commit.parents: commit.file_changes.append(FileChange(b'M', $RELATIVE_TO_PROJECT_ROOT_PATHNAME, b'$(git hash-object -w $FILENAME)', b'100644'))"
# but let's do it as a full-fledged program that imports git_filter_repo
# anyway...

import argparse
import os
import subprocess
try:
  import git_filter_repo as fr
except ImportError:
  raise SystemExit("Error: Couldn't find git_filter_repo.py.  Did you forget to make a symlink to git-filter-repo named git_filter_repo.py or did you forget to put the latter in your PYTHONPATH?")

parser = argparse.ArgumentParser(
          description='Add a file to the root commit(s) of history')
parser.add_argument('--file', type=os.fsencode,
        help=("Relative-path to file whose contents should be added to root commit(s)"))
args = parser.parse_args()
if not args.file:
  raise SystemExit("Error: Need to specify the --file option")
if any([x == b"." or x== b".." for x in args.file.split(b"/")]):
  raise SystemExit(f"Error: Invalid path components in {fr.decode(args.file)}")
if not os.path.isfile(args.file):
  raise SystemExit(f"Error: {fr.decode(args.file)} not found")

fhash = subprocess.check_output(['git', 'hash-object', '-w', args.file]).strip()
fmode = b'100755' if os.access(args.file, os.X_OK) else b'100644'
# FIXME: I've assumed the file wasn't a directory or symlink...

def fixup_commits(commit, metadata):
  if len(commit.parents) == 0:
    commit.file_changes.append(fr.FileChange(b'M', args.file, fhash, fmode))
  # FIXME: What if the history already had a file matching the given name,
  # but which didn't exist until later in history?  Is the intent for the
  # user to keep the other version that existed when it existed, or to
  # overwrite the version for all of history with the specified file?  I
  # don't know, but if it's the latter, we'd need to add an 'else' clause
  # like the following:
  #else:
  #  commit.file_changes = [x for x in commit.file_changes
  #                         if x.filename != args.file]

fr_args = fr.FilteringOptions.parse_args(['--preserve-commit-encoding',
                                          '--force',
                                          '--replace-refs', 'update-no-add'])
filter = fr.RepoFilter(fr_args, commit_callback=fixup_commits)
filter.run()
