Commit ee4071d4 authored by maruel@chromium.org's avatar maruel@chromium.org

Add gclient_scm.GitWrapper.pack()

TEST=none
BUG=none

Review URL: http://codereview.chromium.org/507070

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@35177 0039d316-1c4b-4281-b951-d872f2087c98
parent f7ae6d55
......@@ -6,6 +6,7 @@
import logging
import os
import posixpath
import re
import subprocess
......@@ -13,6 +14,42 @@ import scm
import gclient_utils
class DiffFilterer(object):
"""Simple class which tracks which file is being diffed and
replaces instances of its file name in the original and
working copy lines of the svn diff output."""
index_string = "Index: "
original_prefix = "--- "
working_prefix = "+++ "
def __init__(self, relpath):
# Note that we always use '/' as the path separator to be
# consistent with svn's cygwin-style output on Windows
self._relpath = relpath.replace("\\", "/")
self._current_file = ""
self._replacement_file = ""
def SetCurrentFile(self, file):
self._current_file = file
# Note that we always use '/' as the path separator to be
# consistent with svn's cygwin-style output on Windows
self._replacement_file = posixpath.join(self._relpath, file)
def ReplaceAndPrint(self, line):
print(line.replace(self._current_file, self._replacement_file))
def Filter(self, line):
if (line.startswith(self.index_string)):
self.SetCurrentFile(line[len(self.index_string):])
self.ReplaceAndPrint(line)
else:
if (line.startswith(self.original_prefix) or
line.startswith(self.working_prefix)):
self.ReplaceAndPrint(line)
else:
print line
### SCM abstraction layer
# Factory Method for SCM wrapper creation
......@@ -69,7 +106,7 @@ class SCMWrapper(object):
raise gclient_utils.Error('Unknown command %s' % command)
if not command in dir(self):
raise gclient_utils.Error('Command %s not implemnted in %s wrapper' % (
raise gclient_utils.Error('Command %s not implemented in %s wrapper' % (
command, self.scm_name))
return getattr(self, command)(options, args, file_list)
......@@ -99,6 +136,16 @@ class GitWrapper(SCMWrapper, scm.GIT):
self._Run(['checkout-index', '-a', '--prefix=%s/' % export_path],
redirect_stdout=False)
def pack(self, options, args, file_list):
"""Generates a patch file which can be applied to the root of the
repository."""
__pychecker__ = 'unusednames=file_list,options'
path = os.path.join(self._root_dir, self.relpath)
merge_base = self._Run(['merge-base', 'HEAD', 'origin'])
command = ['diff', merge_base]
filterer = DiffFilterer(self.relpath)
self.RunAndFilterOutput(command, path, False, False, filterer.Filter)
def update(self, options, args, file_list):
"""Runs git to update or transparently checkout the working copy.
......@@ -278,6 +325,17 @@ class SVNWrapper(SCMWrapper, scm.SVN):
command.append(export_path)
self.Run(command, os.path.join(self._root_dir, self.relpath))
def pack(self, options, args, file_list):
"""Generates a patch file which can be applied to the root of the
repository."""
__pychecker__ = 'unusednames=file_list,options'
path = os.path.join(self._root_dir, self.relpath)
command = ['diff']
command.extend(args)
filterer = DiffFilterer(self.relpath)
self.RunAndFilterOutput(command, path, False, False, filterer.Filter)
def update(self, options, args, file_list):
"""Runs SCM to update or transparently checkout the working copy.
......@@ -465,48 +523,3 @@ class SVNWrapper(SCMWrapper, scm.SVN):
# There's no file list to retrieve.
else:
self.RunAndGetFileList(options, command, path, file_list)
def pack(self, options, args, file_list):
"""Generates a patch file which can be applied to the root of the
repository."""
__pychecker__ = 'unusednames=file_list,options'
path = os.path.join(self._root_dir, self.relpath)
command = ['diff']
command.extend(args)
# Simple class which tracks which file is being diffed and
# replaces instances of its file name in the original and
# working copy lines of the svn diff output.
class DiffFilterer(object):
index_string = "Index: "
original_prefix = "--- "
working_prefix = "+++ "
def __init__(self, relpath):
# Note that we always use '/' as the path separator to be
# consistent with svn's cygwin-style output on Windows
self._relpath = relpath.replace("\\", "/")
self._current_file = ""
self._replacement_file = ""
def SetCurrentFile(self, file):
self._current_file = file
# Note that we always use '/' as the path separator to be
# consistent with svn's cygwin-style output on Windows
self._replacement_file = self._relpath + '/' + file
def ReplaceAndPrint(self, line):
print(line.replace(self._current_file, self._replacement_file))
def Filter(self, line):
if (line.startswith(self.index_string)):
self.SetCurrentFile(line[len(self.index_string):])
self.ReplaceAndPrint(line)
else:
if (line.startswith(self.original_prefix) or
line.startswith(self.working_prefix)):
self.ReplaceAndPrint(line)
else:
print line
filterer = DiffFilterer(self.relpath)
self.RunAndFilterOutput(command, path, False, False, filterer.Filter)
......@@ -67,6 +67,38 @@ class GIT(object):
results.append(('%s ' % m.group(1), m.group(2)))
return results
@staticmethod
def RunAndFilterOutput(args,
in_directory,
print_messages,
print_stdout,
filter):
"""Runs a command, optionally outputting to stdout.
stdout is passed line-by-line to the given filter function. If
print_stdout is true, it is also printed to sys.stdout as in Run.
Args:
args: A sequence of command line parameters to be passed.
in_directory: The directory where svn is to be run.
print_messages: Whether to print status messages to stdout about
which commands are being run.
print_stdout: Whether to forward program's output to stdout.
filter: A function taking one argument (a string) which will be
passed each line (with the ending newline character removed) of
program's output for filtering.
Raises:
gclient_utils.Error: An error occurred while running the command.
"""
command = [GIT.COMMAND]
command.extend(args)
gclient_utils.SubprocessCallAndFilter(command,
in_directory,
print_messages,
print_stdout,
filter=filter)
@staticmethod
def GetEmail(repo_root):
"""Retrieves the user email address if known."""
......@@ -333,31 +365,26 @@ class SVN(object):
print_messages,
print_stdout,
filter):
"""Runs svn checkout, update, status, or diff, optionally outputting
to stdout.
The first item in args must be either "checkout", "update",
"status", or "diff".
"""Runs a command, optionally outputting to stdout.
svn's stdout is passed line-by-line to the given filter function. If
stdout is passed line-by-line to the given filter function. If
print_stdout is true, it is also printed to sys.stdout as in Run.
Args:
args: A sequence of command line parameters to be passed to svn.
args: A sequence of command line parameters to be passed.
in_directory: The directory where svn is to be run.
print_messages: Whether to print status messages to stdout about
which Subversion commands are being run.
print_stdout: Whether to forward Subversion's output to stdout.
which commands are being run.
print_stdout: Whether to forward program's output to stdout.
filter: A function taking one argument (a string) which will be
passed each line (with the ending newline character removed) of
Subversion's output for filtering.
program's output for filtering.
Raises:
Error: An error occurred while running the svn command.
gclient_utils.Error: An error occurred while running the command.
"""
command = [SVN.COMMAND]
command.extend(args)
gclient_utils.SubprocessCallAndFilter(command,
in_directory,
print_messages,
......
......@@ -362,8 +362,8 @@ from :3
'COMMAND', 'Capture', 'CaptureStatus', 'FetchUpstreamTuple',
'GenerateDiff', 'GetBranch', 'GetBranchRef', 'GetCheckoutRoot',
'GetEmail', 'GetPatchName', 'GetSVNBranch',
'GetUpstream', 'IsGitSvn', 'ShortBranchName',
'RunCommand', 'cleanup', 'diff', 'export', 'relpath', 'revert',
'GetUpstream', 'IsGitSvn', 'RunAndFilterOutput', 'ShortBranchName',
'RunCommand', 'cleanup', 'diff', 'export', 'pack', 'relpath', 'revert',
'revinfo', 'runhooks', 'scm_name', 'status', 'update', 'url',
]
......
......@@ -119,7 +119,7 @@ from :3
'COMMAND', 'Capture', 'CaptureStatus', 'FetchUpstreamTuple',
'GenerateDiff', 'GetBranch', 'GetBranchRef', 'GetCheckoutRoot',
'GetEmail', 'GetPatchName', 'GetSVNBranch',
'GetUpstream', 'IsGitSvn', 'ShortBranchName',
'GetUpstream', 'IsGitSvn', 'RunAndFilterOutput', 'ShortBranchName',
]
# If this test fails, you should add the relevant test.
self.compareMembers(scm.GIT, members)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment