xref: /aosp_15_r20/external/skia/gn/copy_git_directory.py (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1#! /usr/bin/env python
2# Copyright 2019 Google LLC.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import os
7import shutil
8import subprocess
9import sys
10
11def copy_git_directory(src, dst, out=None):
12  '''
13  Makes a copy of `src` directory in `dst` directory.  If files already exist
14  and are identical, do not touch them.  If extra files or directories exist,
15  remove them.  Assume that `src` is a git directory so that `git ls-files` can
16  be used to enumerate files.  This has the added benefit of ignoring files
17  not tracked by git.  Also, if out is not None, write summary of actions to out.
18  If `dst` is a top-level git directory, the `.git` directory will be removed.
19  '''
20  if not os.path.isdir(src):
21    raise Exception('Directory "%s" does not exist.' % src)
22  if not os.path.isdir(dst):
23    os.makedirs(dst)
24  ls_files = subprocess.check_output([
25      'git', 'ls-files', '-z', '.'], cwd=src).decode('utf-8')
26  src_files = set(p for p in ls_files.split('\0') if p)
27  abs_src = os.path.abspath(src)
28  cwd = os.getcwd()
29  try:
30    os.chdir(dst)
31    def output(out, sym, dst, path):
32      if out:
33        out.write('%s %s%s%s\n' % (sym, dst, os.sep, path))
34    for dirpath, dirnames, filenames in os.walk('.', topdown=False):
35      for filename in filenames:
36        path = os.path.normpath(os.path.join(dirpath, filename))
37        if path not in src_files:
38          output(out, '-', dst, path)
39          os.remove(path)
40      for filename in dirnames:
41        path = os.path.normpath(os.path.join(dirpath, filename))
42        if not os.listdir(path):  # Remove empty subfolders.
43          output(out, '-', dst, path + os.sep)
44          os.rmdir(path)
45    for path in src_files:
46      src_path = os.path.join(abs_src, path)
47      if os.path.exists(path):
48        with open(path) as f1:
49          with open(src_path) as f2:
50            if f1.read() == f2.read():
51              continue
52      output(out, '+', dst, path)
53      shutil.copy2(src_path, path)
54  finally:
55    os.chdir(cwd)
56
57if __name__ == '__main__':
58  if len(sys.argv) != 3:
59    sys.stderr.write('\nUsage:\n  %s SRC_DIR DST_DIR\n\n' % sys.argv[0])
60    sys.exit(1)
61  copy_git_directory(sys.argv[1], sys.argv[2], sys.stdout)
62