Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(74)

Unified Diff: static/upload.py

Issue 2602: git support (Closed) SVN Base: http://rietveld.googlecode.com/svn/trunk/
Patch Set: try two Created 1 year, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side by-side-diff with in-line comments
Download patch
« no previous file | no next file » | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: static/upload.py
diff --git a/static/upload.py b/static/upload.py
index bc479462d3356dfe35e6b7c88a6c04f119f35ff3..a41bd762bdd84fe695fd1ad9917aa7d4a6293fc5 100755
--- a/static/upload.py
+++ b/static/upload.py
@@ -14,9 +14,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Tool for uploading subversion diffs to the codereview app.
+"""Tool for uploading diffs from a version control system to the codereview app.
-Usage summary: upload.py [options] [-- svn_diff_options]
+Usage summary: upload.py [options] [-- diff_options]
+
+Diff options are passed to the diff command of the underlying system.
+
+Supported version control systems:
+ Git
+ Subversion
+
+(It is important for Git users to specify a tree-ish to diff against.)
"""
# This code is derived from appcfg.py in the App Engine SDK (open source),
# and from ASPN recipe #146306.
@@ -30,6 +38,7 @@ import optparse
import os
import re
import socket
+import subprocess
import sys
import urllib
import urllib2
@@ -342,7 +351,7 @@ class HttpRpcServer(AbstractRpcServer):
return opener
-parser = optparse.OptionParser(usage="%prog [options] [-- svn_diff_options]")
+parser = optparse.OptionParser(usage="%prog [options] [-- diff_options]")
parser.add_option("-y", "--assume_yes", action="store_true",
dest="assume_yes", default=False,
help="Assume that the answer to yes/no questions is 'yes'.")
@@ -715,6 +724,51 @@ class SubversionVCS(VersionControlSystem):
return content, status[0:5]
+class GitVCS(VersionControlSystem):
+ """Implementation of the VersionControlSystem interface for Git."""
+
+ def __init__(self):
+ # Map of filename -> hash of base file.
+ self.base_hashes = {}
+
+ def GenerateDiff(self, extra_args):
+ # This is more complicated than svn's GenerateDiff because we must convert
+ # the diff output to include an svn-style "Index:" line as well as record
+ # the hashes of the base files, so we can upload them along with our diff.
+ gitdiff = RunShell("git diff", ["--full-index"] + extra_args)
+ svndiff = []
+ filecount = 0
+ filename = None
+ for line in gitdiff.splitlines():
+ match = re.match(r"diff --git a/(.*) b/.*$", line)
+ if match:
+ filecount += 1
+ filename = match.group(1)
+ svndiff.append("Index: %s\n" % filename)
+ else:
+ # The "index" line in a git diff looks like this (long hashes elided):
+ # index 82c0d44..b2cee3f 100755
+ # We want to save the left hash, as that identifies the base file.
+ match = re.match(r"index (\w+)\.\.", line)
+ if match:
+ self.base_hashes[filename] = match.group(1)
+ svndiff.append(line + "\n")
+ if not filecount:
+ ErrorExit("No valid patches found in output from git diff")
+ return "".join(svndiff)
+
+ def GetUnknownFiles(self):
+ status = RunShell("git ls-files --others", silent_ok=True)
+ return status.splitlines()
+
+ def GetBaseFile(self, filename):
+ hash = self.base_hashes[filename]
+ if hash == "0" * 40: # All-zero hash indicates no base file.
+ return ("", "A")
+ else:
+ return (RunShell("git show", [hash]), "M")
+
+
# NOTE: this function is duplicated in engine.py, keep them in sync.
def SplitPatch(data):
"""Splits a patch into separate pieces for each file.
@@ -787,12 +841,29 @@ def UploadSeparatePatches(issue, rpc_server, patchset, data, options):
def GuessVCS():
"""Helper to guess the version control system.
+ This examines the current directory, guesses which VersionControlSystem
+ we're using, and returns an instance of the appropriate class. Exit with an
+ error if we can't figure it out.
Andi Albrecht 2008/08/19 19:48:34 Thanks for adding some more docstrings and comment
+
Returns:
A VersionControlSystem instance. Exits if the VCS can't be guessed.
"""
+ # Subversion has a .svn in all working directories.
if os.path.isdir('.svn'):
logging.info("Guessed VCS = Subversion")
return SubversionVCS()
+
+ # Git has a command to test if you're in a git tree.
+ # Try running it, but don't die if we don't have git installed.
+ try:
+ subproc = subprocess.Popen(["git", "rev-parse", "--is-inside-work-tree"],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ if subproc.wait() == 0:
+ return GitVCS()
+ except OSError, (errno, message):
+ if errno != 2: # ENOENT -- they don't have git installed.
+ raise
+
ErrorExit(("Could not guess version control system. "
"Are you in a working copy directory?"))
« no previous file | no next file »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld r497