From 65874e1466491ece496805ce1c27aeee66c37c56 Mon Sep 17 00:00:00 2001 From: "tandrii@chromium.org" Date: Fri, 4 Mar 2016 12:03:02 +0000 Subject: [PATCH] git cl: add python implementation of Change-Id generation. This allows to generate new IDs on the fly without installing commit-msg hook and works just fine on Windows. BUG=579183 Review URL: https://codereview.chromium.org/1757133002 git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@299094 0039d316-1c4b-4281-b951-d872f2087c98 --- git_cl.py | 30 ++++++++++++++++++++++++++++++ tests/git_cl_test.py | 16 ++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/git_cl.py b/git_cl.py index d1802cc3c..8f71fd598 100755 --- a/git_cl.py +++ b/git_cl.py @@ -2148,6 +2148,36 @@ def AddChangeIdToCommitMessage(options, args): print >> sys.stderr, 'ERROR: Gerrit commit-msg hook not available.' +def GenerateGerritChangeId(message): + """Returns Ixxxxxx...xxx change id. + + Works the same way as + https://gerrit-review.googlesource.com/tools/hooks/commit-msg + but can be called on demand on all platforms. + + The basic idea is to generate git hash of a state of the tree, original commit + message, author/committer info and timestamps. + """ + lines = [] + tree_hash = RunGitSilent(['write-tree']) + lines.append('tree %s' % tree_hash.strip()) + code, parent = RunGitWithCode(['rev-parse', 'HEAD~0'], suppress_stderr=False) + if code == 0: + lines.append('parent %s' % parent.strip()) + author = RunGitSilent(['var', 'GIT_AUTHOR_IDENT']) + lines.append('author %s' % author.strip()) + committer = RunGitSilent(['var', 'GIT_COMMITTER_IDENT']) + lines.append('committer %s' % committer.strip()) + lines.append('') + # Note: Gerrit's commit-hook actually cleans message of some lines and + # whitespace. This code is not doing this, but it clearly won't decrease + # entropy. + lines.append(message) + change_hash = RunCommand(['git', 'hash-object', '-t', 'commit', '--stdin'], + stdin='\n'.join(lines)) + return 'I%s' % change_hash.strip() + + def GerritUpload(options, args, cl, change): """upload the current branch to gerrit.""" # We assume the remote called "origin" is the one we want. diff --git a/tests/git_cl_test.py b/tests/git_cl_test.py index 4015bb32b..f5b3257c0 100755 --- a/tests/git_cl_test.py +++ b/tests/git_cl_test.py @@ -746,6 +746,22 @@ class TestGitCl(TestCase): self.assertEquals(5, record_calls.times_called) self.assertEquals(0, ret) + def test_gerrit_change_id(self): + self.calls = [ + ((['git', 'write-tree'], ), + 'hashtree'), + ((['git', 'rev-parse', 'HEAD~0'], ), + 'branch-parent'), + ((['git', 'var', 'GIT_AUTHOR_IDENT'], ), + 'A B 1456848326 +0100'), + ((['git', 'var', 'GIT_COMMITTER_IDENT'], ), + 'C D 1456858326 +0100'), + ((['git', 'hash-object', '-t', 'commit', '--stdin'], ), + 'hashchange'), + ] + change_id = git_cl.GenerateGerritChangeId('line1\nline2\n') + self.assertEqual(change_id, 'Ihashchange') + def test_config_gerrit_download_hook(self): self.mock(git_cl, 'FindCodereviewSettingsFile', CodereviewSettingsFileMock) def ParseCodereviewSettingsContent(content):