Index: gclient_scm.py |
diff --git a/gclient_scm.py b/gclient_scm.py |
index cb8e6f31746403e63f9f3fa17e16102cc23cacfd..d46d47eef0c514a72b30da7e159822fafd40c034 100644 |
--- a/gclient_scm.py |
+++ b/gclient_scm.py |
@@ -37,14 +37,14 @@ class NoUsableRevError(gclient_utils.Error): |
class DiffFiltererWrapper(object): |
"""Simple base 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/git diff output.""" |
+ working copy lines of the git diff output.""" |
index_string = None |
original_prefix = "--- " |
working_prefix = "+++ " |
def __init__(self, relpath, print_func): |
# Note that we always use '/' as the path separator to be |
- # consistent with svn's cygwin-style output on Windows |
+ # consistent with cygwin-style output on Windows |
self._relpath = relpath.replace("\\", "/") |
self._current_file = None |
self._print_func = print_func |
@@ -70,10 +70,6 @@ class DiffFiltererWrapper(object): |
self._print_func(line) |
-class SvnDiffFilterer(DiffFiltererWrapper): |
- index_string = "Index: " |
- |
- |
class GitDiffFilterer(DiffFiltererWrapper): |
index_string = "diff --git " |
@@ -90,26 +86,20 @@ class GitDiffFilterer(DiffFiltererWrapper): |
# Factory Method for SCM wrapper creation |
def GetScmName(url): |
- if url: |
- url, _ = gclient_utils.SplitUrlRevision(url) |
- if (url.startswith('git://') or url.startswith('ssh://') or |
- url.startswith('git+http://') or url.startswith('git+https://') or |
- url.endswith('.git') or url.startswith('sso://') or |
- 'googlesource' in url): |
- return 'git' |
- elif (url.startswith('http://') or url.startswith('https://') or |
- url.startswith('svn://') or url.startswith('svn+ssh://')): |
- return 'svn' |
- elif url.startswith('file://'): |
- if url.endswith('.git'): |
- return 'git' |
- return 'svn' |
+ if not url: |
+ return None |
+ url, _ = gclient_utils.SplitUrlRevision(url) |
+ if url.endswith('.git'): |
+ return 'git' |
+ protocol = url.split('://')[0] |
+ if protocol in ( |
+ 'file', 'git', 'git+http', 'git+https', 'http', 'https', 'ssh', 'sso'): |
+ return 'git' |
return None |
def CreateSCM(url, root_dir=None, relpath=None, out_fh=None, out_cb=None): |
SCM_MAP = { |
- 'svn' : SVNWrapper, |
'git' : GitWrapper, |
} |
@@ -192,10 +182,6 @@ class SCMWrapper(object): |
actual_remote_url.replace('\\', '/')): |
actual_remote_url = self._get_first_remote_url(mirror.mirror_path) |
return actual_remote_url |
- |
- # Svn |
- if os.path.exists(os.path.join(self.checkout_path, '.svn')): |
- return scm.SVN.CaptureLocalInfo([], self.checkout_path)['URL'] |
return None |
def DoesRemoteURLMatch(self, options): |
@@ -210,7 +196,7 @@ class SCMWrapper(object): |
== gclient_utils.SplitUrlRevision(self.url)[0].rstrip('/')) |
else: |
# This may occur if the self.checkout_path exists but does not contain a |
- # valid git or svn checkout. |
+ # valid git checkout. |
return False |
def _DeleteOrMove(self, force): |
@@ -503,7 +489,7 @@ class GitWrapper(SCMWrapper): |
# 0) HEAD is detached. Probably from our initial clone. |
# - make sure HEAD is contained by a named ref, then update. |
# Cases 1-4. HEAD is a branch. |
- # 1) current branch is not tracking a remote branch (could be git-svn) |
+ # 1) current branch is not tracking a remote branch |
# - try to rebase onto the new hash or branch |
# 2) current branch is tracking a remote branch with local committed |
# changes, but the DEPS file switched to point to a hash |
@@ -573,22 +559,15 @@ class GitWrapper(SCMWrapper): |
self.Print('_____ %s%s' % (self.relpath, rev_str), timestamp=False) |
elif current_type == 'hash': |
# case 1 |
- if scm.GIT.IsGitSvn(self.checkout_path) and upstream_branch is not None: |
- # Our git-svn branch (upstream_branch) is our upstream |
- self._AttemptRebase(upstream_branch, files, options, |
- newbase=revision, printed_path=printed_path, |
- merge=options.merge) |
- printed_path = True |
- else: |
- # Can't find a merge-base since we don't know our upstream. That makes |
- # this command VERY likely to produce a rebase failure. For now we |
- # assume origin is our upstream since that's what the old behavior was. |
- upstream_branch = self.remote |
- if options.revision or deps_revision: |
- upstream_branch = revision |
- self._AttemptRebase(upstream_branch, files, options, |
- printed_path=printed_path, merge=options.merge) |
- printed_path = True |
+ # Can't find a merge-base since we don't know our upstream. That makes |
+ # this command VERY likely to produce a rebase failure. For now we |
+ # assume origin is our upstream since that's what the old behavior was. |
+ upstream_branch = self.remote |
+ if options.revision or deps_revision: |
+ upstream_branch = revision |
+ self._AttemptRebase(upstream_branch, files, options, |
+ printed_path=printed_path, merge=options.merge) |
+ printed_path = True |
elif rev_type == 'hash': |
# case 2 |
self._AttemptRebase(upstream_branch, files, options, |
@@ -788,16 +767,13 @@ class GitWrapper(SCMWrapper): |
except subprocess2.CalledProcessError: |
merge_base = [] |
self._Run(['diff', '--name-status'] + merge_base, options, |
- stdout=self.out_fh) |
+ stdout=self.out_fh, always=options.verbose) |
if file_list is not None: |
files = self._Capture(['diff', '--name-only'] + merge_base).split() |
file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
def GetUsableRev(self, rev, options): |
- """Finds a useful revision for this repository. |
- |
- If SCM is git-svn and the head revision is less than |rev|, git svn fetch |
- will be called on the source.""" |
+ """Finds a useful revision for this repository.""" |
sha1 = None |
if not os.path.isdir(self.checkout_path): |
raise NoUsableRevError( |
@@ -807,56 +783,23 @@ class GitWrapper(SCMWrapper): |
'For more info, see: ' |
'http://code.google.com/p/chromium/wiki/UsingNewGit' |
'#Initial_checkout' ) % rev) |
- elif rev.isdigit() and len(rev) < 7: |
- # Handles an SVN rev. As an optimization, only verify an SVN revision as |
- # [0-9]{1,6} for now to avoid making a network request. |
- if scm.GIT.IsGitSvn(cwd=self.checkout_path): |
- local_head = scm.GIT.GetGitSvnHeadRev(cwd=self.checkout_path) |
- if not local_head or local_head < int(rev): |
- try: |
- logging.debug('Looking for git-svn configuration optimizations.') |
- if scm.GIT.Capture(['config', '--get', 'svn-remote.svn.fetch'], |
- cwd=self.checkout_path): |
- self._Fetch(options) |
- except subprocess2.CalledProcessError: |
- logging.debug('git config --get svn-remote.svn.fetch failed, ' |
- 'ignoring possible optimization.') |
- if options.verbose: |
- self.Print('Running git svn fetch. This might take a while.\n') |
- scm.GIT.Capture(['svn', 'fetch'], cwd=self.checkout_path) |
- try: |
- sha1 = scm.GIT.GetBlessedSha1ForSvnRev( |
- cwd=self.checkout_path, rev=rev) |
- except gclient_utils.Error, e: |
- sha1 = e.message |
- self.Print('Warning: Could not find a git revision with accurate\n' |
- '.DEPS.git that maps to SVN revision %s. Sync-ing to\n' |
- 'the closest sane git revision, which is:\n' |
- ' %s\n' % (rev, e.message)) |
- if not sha1: |
- raise NoUsableRevError( |
- ( 'It appears that either your git-svn remote is incorrectly\n' |
- 'configured or the revision in your safesync_url is\n' |
- 'higher than git-svn remote\'s HEAD as we couldn\'t find a\n' |
- 'corresponding git hash for SVN rev %s.' ) % rev) |
+ |
+ if scm.GIT.IsValidRevision(cwd=self.checkout_path, rev=rev): |
+ sha1 = rev |
else: |
+ # May exist in origin, but we don't have it yet, so fetch and look |
+ # again. |
+ self._Fetch(options) |
if scm.GIT.IsValidRevision(cwd=self.checkout_path, rev=rev): |
sha1 = rev |
- else: |
- # May exist in origin, but we don't have it yet, so fetch and look |
- # again. |
- self._Fetch(options) |
- if scm.GIT.IsValidRevision(cwd=self.checkout_path, rev=rev): |
- sha1 = rev |
if not sha1: |
raise NoUsableRevError( |
- ( 'We could not find a valid hash for safesync_url response "%s".\n' |
- 'Safesync URLs with a git checkout currently require a git-svn\n' |
- 'remote or a safesync_url that provides git sha1s. Please add a\n' |
- 'git-svn remote or change your safesync_url. For more info, see:\n' |
- 'http://code.google.com/p/chromium/wiki/UsingNewGit' |
- '#Initial_checkout' ) % rev) |
+ ('We could not find a valid hash for safesync_url response "%s".\n' |
+ 'Please ensure that your safesync_url provides git sha1 hashes.\n' |
+ 'For more info, see:\n' |
+ 'http://code.google.com/p/chromium/wiki/UsingNewGit#Initial_checkout' |
+ ) % rev) |
return sha1 |
@@ -1239,480 +1182,3 @@ class GitWrapper(SCMWrapper): |
gclient_utils.CheckCallAndFilterAndHeader(cmd, env=env, **kwargs) |
else: |
gclient_utils.CheckCallAndFilter(cmd, env=env, **kwargs) |
- |
- |
-class SVNWrapper(SCMWrapper): |
- """ Wrapper for SVN """ |
- name = 'svn' |
- _PRINTED_DEPRECATION = False |
- |
- _MESSAGE = ( |
- 'Oh hai! You are using subversion. Chrome infra is eager to get rid of', |
- 'svn support so please switch to git.', |
- 'Tracking bug: http://crbug.com/475320', |
- 'If you are a project owner, you may request git migration assistance at: ', |
- ' https://code.google.com/p/chromium/issues/entry?template=Infra-Git') |
- |
- def __init__(self, *args, **kwargs): |
- super(SVNWrapper, self).__init__(*args, **kwargs) |
- suppress_deprecated_notice = os.environ.get( |
- 'SUPPRESS_DEPRECATED_SVN_NOTICE', False) |
- if not SVNWrapper._PRINTED_DEPRECATION and not suppress_deprecated_notice: |
- SVNWrapper._PRINTED_DEPRECATION = True |
- sys.stderr.write('\n'.join(self._MESSAGE) + '\n') |
- |
- @staticmethod |
- def BinaryExists(): |
- """Returns true if the command exists.""" |
- try: |
- result, version = scm.SVN.AssertVersion('1.4') |
- if not result: |
- raise gclient_utils.Error('SVN version is older than 1.4: %s' % version) |
- return result |
- except OSError: |
- return False |
- |
- def GetCheckoutRoot(self): |
- return scm.SVN.GetCheckoutRoot(self.checkout_path) |
- |
- def GetRevisionDate(self, revision): |
- """Returns the given revision's date in ISO-8601 format (which contains the |
- time zone).""" |
- date = scm.SVN.Capture( |
- ['propget', '--revprop', 'svn:date', '-r', revision], |
- os.path.join(self.checkout_path, '.')) |
- return date.strip() |
- |
- def cleanup(self, options, args, _file_list): |
- """Cleanup working copy.""" |
- self._Run(['cleanup'] + args, options) |
- |
- def diff(self, options, args, _file_list): |
- # NOTE: This function does not currently modify file_list. |
- if not os.path.isdir(self.checkout_path): |
- raise gclient_utils.Error('Directory %s is not present.' % |
- self.checkout_path) |
- self._Run(['diff'] + args, options) |
- |
- def pack(self, _options, args, _file_list): |
- """Generates a patch file which can be applied to the root of the |
- repository.""" |
- if not os.path.isdir(self.checkout_path): |
- raise gclient_utils.Error('Directory %s is not present.' % |
- self.checkout_path) |
- gclient_utils.CheckCallAndFilter( |
- ['svn', 'diff', '-x', '--ignore-eol-style'] + args, |
- cwd=self.checkout_path, |
- print_stdout=False, |
- filter_fn=SvnDiffFilterer(self.relpath, print_func=self.Print).Filter) |
- |
- def update(self, options, args, file_list): |
- """Runs svn to update or transparently checkout the working copy. |
- |
- All updated files will be appended to file_list. |
- |
- Raises: |
- Error: if can't get URL for relative path. |
- """ |
- # Only update if hg is not controlling the directory. |
- hg_path = os.path.join(self.checkout_path, '.hg') |
- if os.path.exists(hg_path): |
- self.Print('________ found .hg directory; skipping %s' % self.relpath) |
- return |
- |
- if args: |
- raise gclient_utils.Error("Unsupported argument(s): %s" % ",".join(args)) |
- |
- # revision is the revision to match. It is None if no revision is specified, |
- # i.e. the 'deps ain't pinned'. |
- url, revision = gclient_utils.SplitUrlRevision(self.url) |
- # Keep the original unpinned url for reference in case the repo is switched. |
- base_url = url |
- managed = True |
- if options.revision: |
- # Override the revision number. |
- revision = str(options.revision) |
- if revision: |
- if revision != 'unmanaged': |
- forced_revision = True |
- # Reconstruct the url. |
- url = '%s@%s' % (url, revision) |
- rev_str = ' at %s' % revision |
- else: |
- managed = False |
- revision = None |
- else: |
- forced_revision = False |
- rev_str = '' |
- |
- exists = os.path.exists(self.checkout_path) |
- if exists and managed: |
- # Git is only okay if it's a git-svn checkout of the right repo. |
- if scm.GIT.IsGitSvn(self.checkout_path): |
- remote_url = scm.GIT.Capture(['config', '--local', '--get', |
- 'svn-remote.svn.url'], |
- cwd=self.checkout_path).rstrip() |
- if remote_url.rstrip('/') == base_url.rstrip('/'): |
- self.Print('\n_____ %s looks like a git-svn checkout. Skipping.' |
- % self.relpath) |
- return # TODO(borenet): Get the svn revision number? |
- |
- # Get the existing scm url and the revision number of the current checkout. |
- if exists and managed: |
- try: |
- from_info = scm.SVN.CaptureLocalInfo( |
- [], os.path.join(self.checkout_path, '.')) |
- except (gclient_utils.Error, subprocess2.CalledProcessError): |
- self._DeleteOrMove(options.force) |
- exists = False |
- |
- BASE_URLS = { |
- '/chrome/trunk/src': 'gs://chromium-svn-checkout/chrome/', |
- '/blink/trunk': 'gs://chromium-svn-checkout/blink/', |
- } |
- WHITELISTED_ROOTS = [ |
- 'svn://svn.chromium.org', |
- 'svn://svn-mirror.golo.chromium.org', |
- ] |
- if not exists: |
- try: |
- # Split out the revision number since it's not useful for us. |
- base_path = urlparse.urlparse(url).path.split('@')[0] |
- # Check to see if we're on a whitelisted root. We do this because |
- # only some svn servers have matching UUIDs. |
- local_parsed = urlparse.urlparse(url) |
- local_root = '%s://%s' % (local_parsed.scheme, local_parsed.netloc) |
- if ('CHROME_HEADLESS' in os.environ |
- and sys.platform == 'linux2' # TODO(hinoka): Enable for win/mac. |
- and base_path in BASE_URLS |
- and local_root in WHITELISTED_ROOTS): |
- |
- # Use a tarball for initial sync if we are on a bot. |
- # Get an unauthenticated gsutil instance. |
- gsutil = download_from_google_storage.Gsutil( |
- GSUTIL_DEFAULT_PATH, boto_path=os.devnull) |
- |
- gs_path = BASE_URLS[base_path] |
- _, out, _ = gsutil.check_call('ls', gs_path) |
- # So that we can get the most recent revision. |
- sorted_items = sorted(out.splitlines()) |
- latest_checkout = sorted_items[-1] |
- |
- tempdir = tempfile.mkdtemp() |
- self.Print('Downloading %s...' % latest_checkout) |
- code, out, err = gsutil.check_call('cp', latest_checkout, tempdir) |
- if code: |
- self.Print('%s\n%s' % (out, err)) |
- raise Exception() |
- filename = latest_checkout.split('/')[-1] |
- tarball = os.path.join(tempdir, filename) |
- self.Print('Unpacking into %s...' % self.checkout_path) |
- gclient_utils.safe_makedirs(self.checkout_path) |
- # TODO(hinoka): Use 7z for windows. |
- cmd = ['tar', '--extract', '--ungzip', |
- '--directory', self.checkout_path, |
- '--file', tarball] |
- gclient_utils.CheckCallAndFilter( |
- cmd, stdout=sys.stdout, print_stdout=True) |
- |
- self.Print('Deleting temp file') |
- gclient_utils.rmtree(tempdir) |
- |
- # Rewrite the repository root to match. |
- tarball_url = scm.SVN.CaptureLocalInfo( |
- ['.'], self.checkout_path)['Repository Root'] |
- tarball_parsed = urlparse.urlparse(tarball_url) |
- tarball_root = '%s://%s' % (tarball_parsed.scheme, |
- tarball_parsed.netloc) |
- |
- if tarball_root != local_root: |
- self.Print('Switching repository root to %s' % local_root) |
- self._Run(['switch', '--relocate', tarball_root, |
- local_root, self.checkout_path], |
- options) |
- except Exception as e: |
- self.Print('We tried to get a source tarball but failed.') |
- self.Print('Resuming normal operations.') |
- self.Print(str(e)) |
- |
- gclient_utils.safe_makedirs(os.path.dirname(self.checkout_path)) |
- # We need to checkout. |
- command = ['checkout', url, self.checkout_path] |
- command = self._AddAdditionalUpdateFlags(command, options, revision) |
- self._RunAndGetFileList(command, options, file_list, self._root_dir) |
- return self.Svnversion() |
- |
- if not managed: |
- self.Print(('________ unmanaged solution; skipping %s' % self.relpath)) |
- if os.path.exists(os.path.join(self.checkout_path, '.svn')): |
- return self.Svnversion() |
- return |
- |
- if 'URL' not in from_info: |
- raise gclient_utils.Error( |
- ('gclient is confused. Couldn\'t get the url for %s.\n' |
- 'Try using @unmanaged.\n%s') % ( |
- self.checkout_path, from_info)) |
- |
- # Look for locked directories. |
- dir_info = scm.SVN.CaptureStatus( |
- None, os.path.join(self.checkout_path, '.')) |
- if any(d[0][2] == 'L' for d in dir_info): |
- try: |
- self._Run(['cleanup', self.checkout_path], options) |
- except subprocess2.CalledProcessError, e: |
- # Get the status again, svn cleanup may have cleaned up at least |
- # something. |
- dir_info = scm.SVN.CaptureStatus( |
- None, os.path.join(self.checkout_path, '.')) |
- |
- # Try to fix the failures by removing troublesome files. |
- for d in dir_info: |
- if d[0][2] == 'L': |
- if d[0][0] == '!' and options.force: |
- # We don't pass any files/directories to CaptureStatus and set |
- # cwd=self.checkout_path, so we should get relative paths here. |
- assert not os.path.isabs(d[1]) |
- path_to_remove = os.path.normpath( |
- os.path.join(self.checkout_path, d[1])) |
- self.Print('Removing troublesome path %s' % path_to_remove) |
- gclient_utils.rmtree(path_to_remove) |
- else: |
- self.Print( |
- 'Not removing troublesome path %s automatically.' % d[1]) |
- if d[0][0] == '!': |
- self.Print('You can pass --force to enable automatic removal.') |
- raise e |
- |
- if from_info['URL'].rstrip('/') != base_url.rstrip('/'): |
- # The repository url changed, need to switch. |
- try: |
- to_info = scm.SVN.CaptureRemoteInfo(url) |
- except (gclient_utils.Error, subprocess2.CalledProcessError): |
- # The url is invalid or the server is not accessible, it's safer to bail |
- # out right now. |
- raise gclient_utils.Error('This url is unreachable: %s' % url) |
- can_switch = ((from_info['Repository Root'] != to_info['Repository Root']) |
- and (from_info['UUID'] == to_info['UUID'])) |
- if can_switch: |
- self.Print('_____ relocating %s to a new checkout' % self.relpath) |
- # We have different roots, so check if we can switch --relocate. |
- # Subversion only permits this if the repository UUIDs match. |
- # Perform the switch --relocate, then rewrite the from_url |
- # to reflect where we "are now." (This is the same way that |
- # Subversion itself handles the metadata when switch --relocate |
- # is used.) This makes the checks below for whether we |
- # can update to a revision or have to switch to a different |
- # branch work as expected. |
- # TODO(maruel): TEST ME ! |
- command = ['switch', '--relocate', |
- from_info['Repository Root'], |
- to_info['Repository Root'], |
- self.relpath] |
- self._Run(command, options, cwd=self._root_dir) |
- from_info['URL'] = from_info['URL'].replace( |
- from_info['Repository Root'], |
- to_info['Repository Root']) |
- else: |
- if not options.force and not options.reset: |
- # Look for local modifications but ignore unversioned files. |
- for status in scm.SVN.CaptureStatus(None, self.checkout_path): |
- if status[0][0] != '?': |
- raise gclient_utils.Error( |
- ('Can\'t switch the checkout to %s; UUID don\'t match and ' |
- 'there is local changes in %s. Delete the directory and ' |
- 'try again.') % (url, self.checkout_path)) |
- # Ok delete it. |
- self.Print('_____ switching %s to a new checkout' % self.relpath) |
- gclient_utils.rmtree(self.checkout_path) |
- # We need to checkout. |
- command = ['checkout', url, self.checkout_path] |
- command = self._AddAdditionalUpdateFlags(command, options, revision) |
- self._RunAndGetFileList(command, options, file_list, self._root_dir) |
- return self.Svnversion() |
- |
- # If the provided url has a revision number that matches the revision |
- # number of the existing directory, then we don't need to bother updating. |
- if not options.force and str(from_info['Revision']) == revision: |
- if options.verbose or not forced_revision: |
- self.Print('_____ %s%s' % (self.relpath, rev_str), timestamp=False) |
- else: |
- command = ['update', self.checkout_path] |
- command = self._AddAdditionalUpdateFlags(command, options, revision) |
- self._RunAndGetFileList(command, options, file_list, self._root_dir) |
- |
- # If --reset and --delete_unversioned_trees are specified, remove any |
- # untracked files and directories. |
- if options.reset and options.delete_unversioned_trees: |
- for status in scm.SVN.CaptureStatus(None, self.checkout_path): |
- full_path = os.path.join(self.checkout_path, status[1]) |
- if (status[0][0] == '?' |
- and os.path.isdir(full_path) |
- and not os.path.islink(full_path)): |
- self.Print('_____ removing unversioned directory %s' % status[1]) |
- gclient_utils.rmtree(full_path) |
- return self.Svnversion() |
- |
- def updatesingle(self, options, args, file_list): |
- filename = args.pop() |
- if scm.SVN.AssertVersion("1.5")[0]: |
- if not os.path.exists(os.path.join(self.checkout_path, '.svn')): |
- # Create an empty checkout and then update the one file we want. Future |
- # operations will only apply to the one file we checked out. |
- command = ["checkout", "--depth", "empty", self.url, self.checkout_path] |
- self._Run(command, options, cwd=self._root_dir) |
- if os.path.exists(os.path.join(self.checkout_path, filename)): |
- os.remove(os.path.join(self.checkout_path, filename)) |
- command = ["update", filename] |
- self._RunAndGetFileList(command, options, file_list) |
- # After the initial checkout, we can use update as if it were any other |
- # dep. |
- self.update(options, args, file_list) |
- else: |
- # If the installed version of SVN doesn't support --depth, fallback to |
- # just exporting the file. This has the downside that revision |
- # information is not stored next to the file, so we will have to |
- # re-export the file every time we sync. |
- if not os.path.exists(self.checkout_path): |
- gclient_utils.safe_makedirs(self.checkout_path) |
- command = ["export", os.path.join(self.url, filename), |
- os.path.join(self.checkout_path, filename)] |
- command = self._AddAdditionalUpdateFlags(command, options, |
- options.revision) |
- self._Run(command, options, cwd=self._root_dir) |
- |
- def revert(self, options, _args, file_list): |
- """Reverts local modifications. Subversion specific. |
- |
- All reverted files will be appended to file_list, even if Subversion |
- doesn't know about them. |
- """ |
- if not os.path.isdir(self.checkout_path): |
- if os.path.exists(self.checkout_path): |
- gclient_utils.rmtree(self.checkout_path) |
- # svn revert won't work if the directory doesn't exist. It needs to |
- # checkout instead. |
- self.Print('_____ %s is missing, synching instead' % self.relpath) |
- # Don't reuse the args. |
- return self.update(options, [], file_list) |
- |
- if not os.path.isdir(os.path.join(self.checkout_path, '.svn')): |
- if os.path.isdir(os.path.join(self.checkout_path, '.git')): |
- self.Print('________ found .git directory; skipping %s' % self.relpath) |
- return |
- if os.path.isdir(os.path.join(self.checkout_path, '.hg')): |
- self.Print('________ found .hg directory; skipping %s' % self.relpath) |
- return |
- if not options.force: |
- raise gclient_utils.Error('Invalid checkout path, aborting') |
- self.Print( |
- '\n_____ %s is not a valid svn checkout, synching instead' % |
- self.relpath) |
- gclient_utils.rmtree(self.checkout_path) |
- # Don't reuse the args. |
- return self.update(options, [], file_list) |
- |
- def printcb(file_status): |
- if file_list is not None: |
- file_list.append(file_status[1]) |
- if logging.getLogger().isEnabledFor(logging.INFO): |
- logging.info('%s%s' % (file_status[0], file_status[1])) |
- else: |
- self.Print(os.path.join(self.checkout_path, file_status[1])) |
- scm.SVN.Revert(self.checkout_path, callback=printcb) |
- |
- # Revert() may delete the directory altogether. |
- if not os.path.isdir(self.checkout_path): |
- # Don't reuse the args. |
- return self.update(options, [], file_list) |
- |
- try: |
- # svn revert is so broken we don't even use it. Using |
- # "svn up --revision BASE" achieve the same effect. |
- # file_list will contain duplicates. |
- self._RunAndGetFileList(['update', '--revision', 'BASE'], options, |
- file_list) |
- except OSError, e: |
- # Maybe the directory disappeared meanwhile. Do not throw an exception. |
- logging.error('Failed to update:\n%s' % str(e)) |
- |
- def revinfo(self, _options, _args, _file_list): |
- """Display revision""" |
- try: |
- return scm.SVN.CaptureRevision(self.checkout_path) |
- except (gclient_utils.Error, subprocess2.CalledProcessError): |
- return None |
- |
- def runhooks(self, options, args, file_list): |
- self.status(options, args, file_list) |
- |
- def status(self, options, args, file_list): |
- """Display status information.""" |
- command = ['status'] + args |
- if not os.path.isdir(self.checkout_path): |
- # svn status won't work if the directory doesn't exist. |
- self.Print(('\n________ couldn\'t run \'%s\' in \'%s\':\n' |
- 'The directory does not exist.') % |
- (' '.join(command), self.checkout_path)) |
- # There's no file list to retrieve. |
- else: |
- self._RunAndGetFileList(command, options, file_list) |
- |
- def GetUsableRev(self, rev, _options): |
- """Verifies the validity of the revision for this repository.""" |
- if not scm.SVN.IsValidRevision(url='%s@%s' % (self.url, rev)): |
- raise NoUsableRevError( |
- ( '%s isn\'t a valid revision. Please check that your safesync_url is\n' |
- 'correct.') % rev) |
- return rev |
- |
- def FullUrlForRelativeUrl(self, url): |
- # Find the forth '/' and strip from there. A bit hackish. |
- return '/'.join(self.url.split('/')[:4]) + url |
- |
- def _Run(self, args, options, **kwargs): |
- """Runs a commands that goes to stdout.""" |
- kwargs.setdefault('cwd', self.checkout_path) |
- gclient_utils.CheckCallAndFilterAndHeader(['svn'] + args, |
- always=options.verbose, **kwargs) |
- |
- def Svnversion(self): |
- """Runs the lowest checked out revision in the current project.""" |
- info = scm.SVN.CaptureLocalInfo([], os.path.join(self.checkout_path, '.')) |
- return info['Revision'] |
- |
- def _RunAndGetFileList(self, args, options, file_list, cwd=None): |
- """Runs a commands that goes to stdout and grabs the file listed.""" |
- cwd = cwd or self.checkout_path |
- scm.SVN.RunAndGetFileList( |
- options.verbose, |
- args + ['--ignore-externals'], |
- cwd=cwd, |
- file_list=file_list) |
- |
- @staticmethod |
- def _AddAdditionalUpdateFlags(command, options, revision): |
- """Add additional flags to command depending on what options are set. |
- command should be a list of strings that represents an svn command. |
- |
- This method returns a new list to be used as a command.""" |
- new_command = command[:] |
- if revision: |
- new_command.extend(['--revision', str(revision).strip()]) |
- # We don't want interaction when jobs are used. |
- if options.jobs > 1: |
- new_command.append('--non-interactive') |
- # --force was added to 'svn update' in svn 1.5. |
- # --accept was added to 'svn update' in svn 1.6. |
- if not scm.SVN.AssertVersion('1.5')[0]: |
- return new_command |
- |
- # It's annoying to have it block in the middle of a sync, just sensible |
- # defaults. |
- if options.force: |
- new_command.append('--force') |
- if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
- new_command.extend(('--accept', 'theirs-conflict')) |
- elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
- new_command.extend(('--accept', 'postpone')) |
- return new_command |