| OLD | NEW | 
|     1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |     1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|     2 # Use of this source code is governed by a BSD-style license that can be |     2 # Use of this source code is governed by a BSD-style license that can be | 
|     3 # found in the LICENSE file. |     3 # found in the LICENSE file. | 
|     4  |     4  | 
|     5 """Gclient-specific SCM-specific operations.""" |     5 """Gclient-specific SCM-specific operations.""" | 
|     6  |     6  | 
|     7 import collections |     7 import collections | 
|     8 import logging |     8 import logging | 
|     9 import os |     9 import os | 
|    10 import posixpath |    10 import posixpath | 
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   375       raise gclient_utils.Error('\n____ %s%s\n' |   375       raise gclient_utils.Error('\n____ %s%s\n' | 
|   376                                 '\tPath is not a git repo. No .git dir.\n' |   376                                 '\tPath is not a git repo. No .git dir.\n' | 
|   377                                 '\tTo resolve:\n' |   377                                 '\tTo resolve:\n' | 
|   378                                 '\t\trm -rf %s\n' |   378                                 '\t\trm -rf %s\n' | 
|   379                                 '\tAnd run gclient sync again\n' |   379                                 '\tAnd run gclient sync again\n' | 
|   380                                 % (self.relpath, rev_str, self.relpath)) |   380                                 % (self.relpath, rev_str, self.relpath)) | 
|   381  |   381  | 
|   382     # See if the url has changed (the unittests use git://foo for the url, let |   382     # See if the url has changed (the unittests use git://foo for the url, let | 
|   383     # that through). |   383     # that through). | 
|   384     current_url = self._Capture(['config', 'remote.origin.url']) |   384     current_url = self._Capture(['config', 'remote.origin.url']) | 
 |   385     return_early = False | 
|   385     # TODO(maruel): Delete url != 'git://foo' since it's just to make the |   386     # TODO(maruel): Delete url != 'git://foo' since it's just to make the | 
|   386     # unit test pass. (and update the comment above) |   387     # unit test pass. (and update the comment above) | 
|   387     # Skip url auto-correction if remote.origin.gclient-auto-fix-url is set. |   388     # Skip url auto-correction if remote.origin.gclient-auto-fix-url is set. | 
|   388     # This allows devs to use experimental repos which have a different url |   389     # This allows devs to use experimental repos which have a different url | 
|   389     # but whose branch(s) are the same as official repos. |   390     # but whose branch(s) are the same as official repos. | 
|   390     if (current_url != url and |   391     if (current_url != url and | 
|   391         url != 'git://foo' and |   392         url != 'git://foo' and | 
|   392         subprocess2.capture( |   393         subprocess2.capture( | 
|   393             ['git', 'config', 'remote.origin.gclient-auto-fix-url'], |   394             ['git', 'config', 'remote.origin.gclient-auto-fix-url'], | 
|   394             cwd=self.checkout_path).strip() != 'False'): |   395             cwd=self.checkout_path).strip() != 'False'): | 
|   395       print('_____ switching %s to a new upstream' % self.relpath) |   396       print('_____ switching %s to a new upstream' % self.relpath) | 
|   396       # Make sure it's clean |   397       # Make sure it's clean | 
|   397       self._CheckClean(rev_str) |   398       self._CheckClean(rev_str) | 
|   398       # Switch over to the new upstream |   399       # Switch over to the new upstream | 
|   399       self._Run(['remote', 'set-url', 'origin', url], options) |   400       self._Run(['remote', 'set-url', 'origin', url], options) | 
|   400       self._FetchAndReset(revision, file_list, options) |   401       self._FetchAndReset(revision, file_list, options) | 
 |   402       return_early = True | 
 |   403  | 
 |   404     # Need to do this in the normal path as well as in the post-remote-switch | 
 |   405     # path. | 
 |   406     self._PossiblySwitchCache(url, options) | 
 |   407  | 
 |   408     if return_early: | 
|   401       return |   409       return | 
|   402  |   410  | 
|   403     if not self._IsValidGitRepo(): |   411     if not self._IsValidGitRepo(): | 
|   404       # .git directory is hosed for some reason, set it back up. |   412       # .git directory is hosed for some reason, set it back up. | 
|   405       print('_____ %s/.git is corrupted, rebuilding' % self.relpath) |   413       print('_____ %s/.git is corrupted, rebuilding' % self.relpath) | 
|   406       self._Run(['init'], options) |   414       self._Run(['init'], options) | 
|   407       self._Run(['remote', 'set-url', 'origin', url], options) |   415       self._Run(['remote', 'set-url', 'origin', url], options) | 
|   408  |   416  | 
|   409     if not self._HasHead(): |   417     if not self._HasHead(): | 
|   410       # Previous checkout was aborted before branches could be created in repo, |   418       # Previous checkout was aborted before branches could be created in repo, | 
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   728   @staticmethod |   736   @staticmethod | 
|   729   def _NormalizeGitURL(url): |   737   def _NormalizeGitURL(url): | 
|   730     '''Takes a git url, strips the scheme, and ensures it ends with '.git'.''' |   738     '''Takes a git url, strips the scheme, and ensures it ends with '.git'.''' | 
|   731     idx = url.find('://') |   739     idx = url.find('://') | 
|   732     if idx != -1: |   740     if idx != -1: | 
|   733       url = url[idx+3:] |   741       url = url[idx+3:] | 
|   734     if not url.endswith('.git'): |   742     if not url.endswith('.git'): | 
|   735       url += '.git' |   743       url += '.git' | 
|   736     return url |   744     return url | 
|   737  |   745  | 
 |   746   def _PossiblySwitchCache(self, url, options): | 
 |   747     """Handles switching a repo from with-cache to direct, or vice versa. | 
 |   748  | 
 |   749     When we go from direct to with-cache, the remote url changes from the | 
 |   750     'real' url to the local file url (in cache_dir). Therefore, this function | 
 |   751     assumes that |url| points to the correctly-switched-over local file url, if | 
 |   752     we're in cache_mode. | 
 |   753  | 
 |   754     When we go from with-cache to direct, assume that the normal url-switching | 
 |   755     code already flipped the remote over, and we just need to repack and break | 
 |   756     the dependency to the cache. | 
 |   757     """ | 
 |   758  | 
 |   759     altfile = os.path.join( | 
 |   760         self.checkout_path, '.git', 'objects', 'info', 'alternates') | 
 |   761     if self.cache_dir: | 
 |   762       if not os.path.exists(altfile): | 
 |   763         try: | 
 |   764           with open(altfile, 'wa') as f: | 
 |   765             f.write(os.path.join(url, 'objects')) | 
 |   766           # pylint: disable=C0301 | 
 |   767           # This dance is necessary according to emperical evidence, also at: | 
 |   768           # http://lists-archives.com/git/713652-retrospectively-add-alternates-
      to-a-repository.html | 
 |   769           self._Run(['repack', '-ad'], options) | 
 |   770           self._Run(['repack', '-adl'], options) | 
 |   771         except Exception: | 
 |   772           # If something goes wrong, try to remove the altfile so we'll go down | 
 |   773           # this path again next time. | 
 |   774           try: | 
 |   775             os.remove(altfile) | 
 |   776           except Exception: | 
 |   777             pass | 
 |   778           raise | 
 |   779     else: | 
 |   780       if os.path.exists(altfile): | 
 |   781         self._Run(['repack', '-a'], options) | 
 |   782         os.remove(altfile) | 
 |   783  | 
|   738   def _CreateOrUpdateCache(self, url, options): |   784   def _CreateOrUpdateCache(self, url, options): | 
|   739     """Make a new git mirror or update existing mirror for |url|, and return the |   785     """Make a new git mirror or update existing mirror for |url|, and return the | 
|   740     mirror URI to clone from. |   786     mirror URI to clone from. | 
|   741  |   787  | 
|   742     If no cache-dir is specified, just return |url| unchanged. |   788     If no cache-dir is specified, just return |url| unchanged. | 
|   743     """ |   789     """ | 
|   744     if not self.cache_dir: |   790     if not self.cache_dir: | 
|   745       return url |   791       return url | 
|   746  |   792  | 
|   747     # Replace - with -- to avoid ambiguity. / with - to flatten folder structure |   793     # Replace - with -- to avoid ambiguity. / with - to flatten folder structure | 
|   748     folder = os.path.join( |   794     folder = os.path.join( | 
|   749       self.cache_dir, |   795       self.cache_dir, | 
|   750       self._NormalizeGitURL(url).replace('-', '--').replace('/', '-')) |   796       self._NormalizeGitURL(url).replace('-', '--').replace('/', '-')) | 
 |   797     altfile = os.path.join(folder, 'objects', 'info', 'alternates') | 
 |   798  | 
 |   799     # If we're bringing an old cache up to date or cloning a new cache, and the | 
 |   800     # existing repo is currently a direct clone, use its objects to help out | 
 |   801     # the fetch here. | 
 |   802     checkout_objects = os.path.join(self.checkout_path, '.git', 'objects') | 
 |   803     checkout_altfile = os.path.join(checkout_objects, 'info', 'alternates') | 
 |   804     use_reference = ( | 
 |   805         os.path.exists(checkout_objects) and | 
 |   806         not os.path.exists(checkout_altfile)) | 
|   751  |   807  | 
|   752     v = ['-v'] if options.verbose else [] |   808     v = ['-v'] if options.verbose else [] | 
|   753     filter_fn = lambda l: '[up to date]' not in l |   809     filter_fn = lambda l: '[up to date]' not in l | 
|   754     with self.cache_locks[folder]: |   810     with self.cache_locks[folder]: | 
|   755       gclient_utils.safe_makedirs(self.cache_dir) |   811       gclient_utils.safe_makedirs(self.cache_dir) | 
|   756       if not os.path.exists(os.path.join(folder, 'config')): |   812       if not os.path.exists(os.path.join(folder, 'config')): | 
|   757         gclient_utils.rmtree(folder) |   813         gclient_utils.rmtree(folder) | 
|   758         self._Run(['clone'] + v + ['-c', 'core.deltaBaseCacheLimit=2g', |   814         cmd = ['clone'] + v + ['-c', 'core.deltaBaseCacheLimit=2g', | 
|   759                                    '--progress', '--mirror', url, folder], |   815                                '--progress', '--mirror'] | 
 |   816  | 
 |   817         if use_reference: | 
 |   818           cmd += ['--reference', os.path.abspath(self.checkout_path)] | 
 |   819  | 
 |   820         self._Run(cmd + [url, folder], | 
|   760                   options, git_filter=True, filter_fn=filter_fn, |   821                   options, git_filter=True, filter_fn=filter_fn, | 
|   761                   cwd=self.cache_dir) |   822                   cwd=self.cache_dir) | 
|   762       else: |   823       else: | 
|   763         # For now, assert that host/path/to/repo.git is identical. We may want |   824         # For now, assert that host/path/to/repo.git is identical. We may want | 
|   764         # to relax this restriction in the future to allow for smarter cache |   825         # to relax this restriction in the future to allow for smarter cache | 
|   765         # repo update schemes (such as pulling the same repo, but from a |   826         # repo update schemes (such as pulling the same repo, but from a | 
|   766         # different host). |   827         # different host). | 
|   767         existing_url = self._Capture(['config', 'remote.origin.url'], |   828         existing_url = self._Capture(['config', 'remote.origin.url'], | 
|   768                                      cwd=folder) |   829                                      cwd=folder) | 
|   769         assert self._NormalizeGitURL(existing_url) == self._NormalizeGitURL(url) |   830         assert self._NormalizeGitURL(existing_url) == self._NormalizeGitURL(url) | 
|   770  |   831  | 
 |   832         if use_reference: | 
 |   833           with open(altfile, 'w') as f: | 
 |   834             f.write(os.path.abspath(checkout_objects)) | 
 |   835  | 
|   771         # Would normally use `git remote update`, but it doesn't support |   836         # Would normally use `git remote update`, but it doesn't support | 
|   772         # --progress, so use fetch instead. |   837         # --progress, so use fetch instead. | 
|   773         self._Run(['fetch'] + v + ['--multiple', '--progress', '--all'], |   838         self._Run(['fetch'] + v + ['--multiple', '--progress', '--all'], | 
|   774                   options, git_filter=True, filter_fn=filter_fn, cwd=folder) |   839                   options, git_filter=True, filter_fn=filter_fn, cwd=folder) | 
 |   840  | 
 |   841       # If the clone has an object dependency on the existing repo, break it | 
 |   842       # with repack and remove the linkage. | 
 |   843       if os.path.exists(altfile): | 
 |   844         self._Run(['repack', '-a'], options, cwd=folder) | 
 |   845         os.remove(altfile) | 
|   775     return folder |   846     return folder | 
|   776  |   847  | 
|   777   def _Clone(self, revision, url, options): |   848   def _Clone(self, revision, url, options): | 
|   778     """Clone a git repository from the given URL. |   849     """Clone a git repository from the given URL. | 
|   779  |   850  | 
|   780     Once we've cloned the repo, we checkout a working branch if the specified |   851     Once we've cloned the repo, we checkout a working branch if the specified | 
|   781     revision is a branch head. If it is a tag or a specific commit, then we |   852     revision is a branch head. If it is a tag or a specific commit, then we | 
|   782     leave HEAD detached as it makes future updates simpler -- in this case the |   853     leave HEAD detached as it makes future updates simpler -- in this case the | 
|   783     user should first create a new branch or switch to an existing branch before |   854     user should first create a new branch or switch to an existing branch before | 
|   784     making changes in the repo.""" |   855     making changes in the repo.""" | 
| (...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1435       new_command.append('--force') |  1506       new_command.append('--force') | 
|  1436       if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |  1507       if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 
|  1437         new_command.extend(('--accept', 'theirs-conflict')) |  1508         new_command.extend(('--accept', 'theirs-conflict')) | 
|  1438     elif options.manually_grab_svn_rev: |  1509     elif options.manually_grab_svn_rev: | 
|  1439       new_command.append('--force') |  1510       new_command.append('--force') | 
|  1440       if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |  1511       if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 
|  1441         new_command.extend(('--accept', 'postpone')) |  1512         new_command.extend(('--accept', 'postpone')) | 
|  1442     elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |  1513     elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 
|  1443       new_command.extend(('--accept', 'postpone')) |  1514       new_command.extend(('--accept', 'postpone')) | 
|  1444     return new_command |  1515     return new_command | 
| OLD | NEW |