@ -4,14 +4,12 @@
""" Gclient-specific SCM-specific operations. """
import collections
import logging
import os
import posixpath
import re
import sys
import tempfile
import threading
import traceback
import urlparse
@ -148,9 +146,6 @@ class GitWrapper(SCMWrapper):
remote = ' origin '
cache_dir = None
# If a given cache is used in a solution more than once, prevent multiple
# threads from updating it simultaneously.
cache_locks = collections . defaultdict ( threading . Lock )
def __init__ ( self , url = None , root_dir = None , relpath = None ) :
""" Removes ' git+ ' fake prefix from git URL. """
@ -352,10 +347,6 @@ class GitWrapper(SCMWrapper):
self . _FetchAndReset ( revision , file_list , options )
return_early = True
# Need to do this in the normal path as well as in the post-remote-switch
# path.
self . _PossiblySwitchCache ( url , options )
if return_early :
return self . _Capture ( [ ' rev-parse ' , ' --verify ' , ' HEAD ' ] )
@ -681,54 +672,6 @@ class GitWrapper(SCMWrapper):
base_url = self . url
return base_url [ : base_url . rfind ( ' / ' ) ] + url
@staticmethod
def _NormalizeGitURL ( url ) :
''' Takes a git url, strips the scheme, and ensures it ends with ' .git ' . '''
idx = url . find ( ' :// ' )
if idx != - 1 :
url = url [ idx + 3 : ]
if not url . endswith ( ' .git ' ) :
url + = ' .git '
return url
def _PossiblySwitchCache ( self , url , options ) :
""" Handles switching a repo from with-cache to direct, or vice versa.
When we go from direct to with - cache , the remote url changes from the
' real ' url to the local file url ( in cache_dir ) . Therefore , this function
assumes that | url | points to the correctly - switched - over local file url , if
we ' re in cache_mode.
When we go from with - cache to direct , assume that the normal url - switching
code already flipped the remote over , and we just need to repack and break
the dependency to the cache .
"""
altfile = os . path . join (
self . checkout_path , ' .git ' , ' objects ' , ' info ' , ' alternates ' )
if self . cache_dir :
if not os . path . exists ( altfile ) :
try :
with open ( altfile , ' w ' ) as f :
f . write ( os . path . join ( url , ' objects ' ) )
# pylint: disable=C0301
# This dance is necessary according to emperical evidence, also at:
# http://lists-archives.com/git/713652-retrospectively-add-alternates-to-a-repository.html
self . _Run ( [ ' repack ' , ' -ad ' ] , options )
self . _Run ( [ ' repack ' , ' -adl ' ] , options )
except Exception :
# If something goes wrong, try to remove the altfile so we'll go down
# this path again next time.
try :
os . remove ( altfile )
except OSError as e :
print >> sys . stderr , " FAILED: os.remove( ' %s ' ) -> %s " % ( altfile , e )
raise
else :
if os . path . exists ( altfile ) :
self . _Run ( [ ' repack ' , ' -a ' ] , options )
os . remove ( altfile )
def _CreateOrUpdateCache ( self , url , options ) :
""" Make a new git mirror or update existing mirror for |url|, and return the
mirror URI to clone from .
@ -737,60 +680,12 @@ class GitWrapper(SCMWrapper):
"""
if not self . cache_dir :
return url
# Replace - with -- to avoid ambiguity. / with - to flatten folder structure
folder = os . path . join (
self . cache_dir ,
self . _NormalizeGitURL ( url ) . replace ( ' - ' , ' -- ' ) . replace ( ' / ' , ' - ' ) )
altfile = os . path . join ( folder , ' objects ' , ' info ' , ' alternates ' )
# If we're bringing an old cache up to date or cloning a new cache, and the
# existing repo is currently a direct clone, use its objects to help out
# the fetch here.
checkout_objects = os . path . join ( self . checkout_path , ' .git ' , ' objects ' )
checkout_altfile = os . path . join ( checkout_objects , ' info ' , ' alternates ' )
use_reference = (
os . path . exists ( checkout_objects ) and
not os . path . exists ( checkout_altfile ) )
v = [ ' -v ' ] if options . verbose else [ ]
filter_fn = lambda l : ' [up to date] ' not in l
with self . cache_locks [ folder ] :
gclient_utils . safe_makedirs ( self . cache_dir )
if not os . path . exists ( os . path . join ( folder , ' config ' ) ) :
gclient_utils . rmtree ( folder )
cmd = [ ' clone ' ] + v + [ ' -c ' , ' core.deltaBaseCacheLimit=2g ' ,
' --progress ' , ' --bare ' ]
if use_reference :
cmd + = [ ' --reference ' , os . path . abspath ( self . checkout_path ) ]
self . _Run ( cmd + [ url , folder ] ,
options , filter_fn = filter_fn , cwd = self . cache_dir , retry = True )
else :
# For now, assert that host/path/to/repo.git is identical. We may want
# to relax this restriction in the future to allow for smarter cache
# repo update schemes (such as pulling the same repo, but from a
# different host).
existing_url = self . _Capture ( [ ' config ' , ' remote. %s .url ' % self . remote ] ,
cwd = folder )
assert self . _NormalizeGitURL ( existing_url ) == self . _NormalizeGitURL ( url )
if use_reference :
with open ( altfile , ' w ' ) as f :
f . write ( os . path . abspath ( checkout_objects ) )
# Would normally use `git remote update`, but it doesn't support
# --progress, so use fetch instead.
self . _Run ( [ ' fetch ' ] + v + [ ' --multiple ' , ' --progress ' , ' --all ' ] ,
options , filter_fn = filter_fn , cwd = folder , retry = True )
# If the clone has an object dependency on the existing repo, break it
# with repack and remove the linkage.
if os . path . exists ( altfile ) :
self . _Run ( [ ' repack ' , ' -a ' ] , options , cwd = folder )
os . remove ( altfile )
return folder
self . _Run ( [ ' cache ' , ' populate ' ] + v +
[ ' --shallow ' , ' --cache-dir ' , self . cache_dir , url ] ,
options , cwd = self . _root_dir , retry = True )
return self . _Run ( [ ' cache ' , ' exists ' , ' --cache-dir ' , self . cache_dir , url ] ,
options ) . strip ( )
def _Clone ( self , revision , url , options ) :
""" Clone a git repository from the given URL.
@ -1044,7 +939,7 @@ class GitWrapper(SCMWrapper):
stdout = kwargs . get ( ' stdout ' , sys . stdout )
stdout . write ( ' \n ________ running \' git %s \' in \' %s \' \n ' % (
' ' . join ( args ) , kwargs [ ' cwd ' ] ) )
gclient_utils . CheckCallAndFilter ( [ ' git ' ] + args , * * kwargs )
return gclient_utils . CheckCallAndFilter ( [ ' git ' ] + args , * * kwargs )
class SVNWrapper ( SCMWrapper ) :