Support GIT upstream
Add the support to check how far a project is behind upstream git.
Still need to manually run git merge. But this tool can help update
METADATA. :)
Test: ./updater.sh update perf_data_converter
Change-Id: Ic46a0eb723ae22f0fc7d61a67a14299761b564a4
diff --git a/git_utils.py b/git_utils.py
new file mode 100644
index 0000000..8e8f96d
--- /dev/null
+++ b/git_utils.py
@@ -0,0 +1,77 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the 'License');
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an 'AS IS' BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+'''Helper functions to communicate with Git.'''
+
+import datetime
+import subprocess
+
+
+def _run(cmd, cwd):
+ """Runs a command with stdout and stderr redirected."""
+ return subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ check=True, cwd=cwd)
+
+def fetch(proj_path, remote_names):
+ """Runs git fetch.
+
+ Args:
+ proj_path: Path to Git repository.
+ remote_names: Array of string to specify remote names.
+ """
+ _run(['git', 'fetch', '--multiple'] + remote_names, cwd=proj_path)
+
+def add_remote(proj_path, name, url):
+ """Adds a git remote.
+
+ Args:
+ proj_path: Path to Git repository.
+ name: Name of the new remote.
+ url: Url of the new remote.
+ """
+ _run(['git', 'remote', 'add', name, url], cwd=proj_path)
+
+def list_remotes(proj_path):
+ """Lists all Git remotes.
+
+ Args:
+ proj_path: Path to Git repository.
+
+ Returns:
+ A dict from remote name to remote url.
+ """
+ out = _run(['git', 'remote', '-v'], proj_path)
+ lines = out.stdout.decode('utf-8').splitlines()
+ return dict([line.split()[0:2] for line in lines])
+
+def get_commits_ahead(proj_path, branch, base_branch):
+ """Lists commits in `branch` but not `base_branch`."""
+ out = _run(['git', 'rev-list', '--left-only',
+ '{}...{}'.format(branch, base_branch)],
+ proj_path)
+ return out.stdout.decode('utf-8').splitlines()
+
+def get_commit_time(proj_path, commit):
+ """Gets commit time of one commit."""
+ out = _run(['git', 'show', '-s', '--format=%ct', commit], cwd=proj_path)
+ return datetime.datetime.fromtimestamp(int(out.stdout))
+
+def list_remote_branches(proj_path, remote_name):
+ """Lists all branches for a remote."""
+ out = _run(['git', 'branch', '-r'], cwd=proj_path)
+ lines = out.stdout.decode('utf-8').splitlines()
+ stripped = [line.strip() for line in lines]
+ remote_path = remote_name + '/'
+ remote_path_len = len(remote_path)
+ return [line[remote_path_len:] for line in stripped
+ if line.startswith(remote_path)]