@ -29,13 +29,6 @@ import scm
import subprocess2
# Attempt |MAX_TRY| times to find a free port. Each time select one port at
# random from the range [|PORT_START|, |PORT_END|].
MAX_TRY = 10
PORT_START = 20000
PORT_END = 65535
def write ( path , content ) :
f = open ( path , ' wb ' )
f . write ( content . encode ( ) )
@ -82,63 +75,6 @@ def commit_git(repo):
return rev
def port_is_free ( host , port ) :
s = socket . socket ( )
try :
return s . connect_ex ( ( host , port ) ) != 0
finally :
s . close ( )
def find_free_port ( host ) :
""" Finds a listening port free to listen to. """
for _ in range ( MAX_TRY ) :
base_port = random . randint ( PORT_START , PORT_END )
if port_is_free ( host , base_port ) :
return base_port
assert False , ' Having issues finding an available port '
def wait_for_port_to_bind ( host , port , process ) :
try :
start = datetime . datetime . utcnow ( )
maxdelay = datetime . timedelta ( seconds = 30 )
while ( datetime . datetime . utcnow ( ) - start ) < maxdelay :
sock = socket . socket ( )
try :
sock . connect ( ( host , port ) )
logging . debug ( ' %d is now bound ' % port )
return
except ( socket . error , EnvironmentError ) :
# Sleep a little bit to avoid spinning too much.
time . sleep ( 0.2 )
logging . debug ( ' %d is still not bound ' % port )
finally :
sock . close ( )
# The process failed to bind. Kill it and dump its ouput.
process . kill ( )
stdout , stderr = process . communicate ( )
logging . debug ( ' %s ' % stdout )
logging . error ( ' %s ' % stderr )
assert False , ' %d is still not bound ' % port
def wait_for_port_to_free ( host , port ) :
start = datetime . datetime . utcnow ( )
maxdelay = datetime . timedelta ( seconds = 30 )
while ( datetime . datetime . utcnow ( ) - start ) < maxdelay :
try :
sock = socket . socket ( )
sock . connect ( ( host , port ) )
logging . debug ( ' %d was bound, waiting to free ' % port )
except ( socket . error , EnvironmentError ) :
logging . debug ( ' %d now free ' % port )
return
finally :
sock . close ( )
assert False , ' %d is still bound ' % port
class FakeReposBase ( object ) :
""" Generate git repositories to test gclient functionality.
@ -164,12 +100,9 @@ class FakeReposBase(object):
# self.git_hashes[repo][rev][1] for it's tree snapshot.
# It is 1-based too.
self . git_hashes = { }
self . gitdaemon = None
self . git_pid_file_name = None
self . git_root = None
self . git_dirty = False
self . git_port = None
self . git_base = None
self . initialized = False
@property
def root_dir ( self ) :
@ -177,22 +110,15 @@ class FakeReposBase(object):
def set_up ( self ) :
""" All late initialization comes here. """
self . cleanup_dirt ( )
if not self . root_dir :
try :
# self.root_dir is not set before this call.
self . trial . set_up ( )
self . git_ root = join ( self . root_dir , ' git ' )
self . git_ base = join ( self . root_dir , ' git ' ) + os . sep
finally :
# Registers cleanup.
atexit . register ( self . tear_down )
def cleanup_dirt ( self ) :
""" For each dirty repository, destroy it. """
if self . git_dirty :
if not self . tear_down_git ( ) :
logging . error ( ' Using both leaking checkout and git dirty checkout ' )
def tear_down ( self ) :
""" Kills the servers and delete the directories. """
self . tear_down_git ( )
@ -201,28 +127,10 @@ class FakeReposBase(object):
self . trial = None
def tear_down_git ( self ) :
if self . gitdaemon :
logging . debug ( ' Killing git-daemon pid %s ' % self . gitdaemon . pid )
self . gitdaemon . kill ( )
self . gitdaemon = None
if self . git_pid_file_name :
pid = int ( open ( self . git_pid_file_name ) . read ( ) )
logging . debug ( ' Killing git daemon pid %s ' % pid )
try :
subprocess2 . kill_pid ( pid )
except OSError as e :
if e . errno != errno . ESRCH : # no such process
raise
os . remove ( self . git_pid_file_name )
self . git_pid_file_name = None
wait_for_port_to_free ( self . host , self . git_port )
self . git_port = None
self . git_base = None
if not self . trial . SHOULD_LEAK :
logging . debug ( ' Removing %s ' % self . git_root )
gclient_utils . rmtree ( self . git_root )
else :
return False
if self . trial . SHOULD_LEAK :
return False
logging . debug ( ' Removing %s ' % self . git_base )
gclient_utils . rmtree ( self . git_base )
return True
@staticmethod
@ -245,41 +153,17 @@ class FakeReposBase(object):
def set_up_git ( self ) :
""" Creates git repositories and start the servers. """
self . set_up ( )
if self . gitdaemon :
if self . initialized :
return True
assert self . git_pid_file_name == None , self . git_pid_file_name
try :
subprocess2 . check_output ( [ ' git ' , ' --version ' ] )
except ( OSError , subprocess2 . CalledProcessError ) :
return False
for repo in [ ' repo_ %d ' % r for r in range ( 1 , self . NB_GIT_REPOS + 1 ) ] :
subprocess2 . check_call ( [ ' git ' , ' init ' , ' -q ' , join ( self . git_ root , repo ) ] )
subprocess2 . check_call ( [ ' git ' , ' init ' , ' -q ' , join ( self . git_ base , repo ) ] )
self . git_hashes [ repo ] = [ ( None , None ) ]
git_pid_file = tempfile . NamedTemporaryFile ( delete = False )
self . git_pid_file_name = git_pid_file . name
git_pid_file . close ( )
self . git_port = find_free_port ( self . host )
self . git_base = ' git:// %s : %d /git/ ' % ( self . host , self . git_port )
cmd = [ ' git ' , ' daemon ' ,
' --export-all ' ,
' --reuseaddr ' ,
' --base-path= ' + self . root_dir ,
' --pid-file= ' + self . git_pid_file_name ,
' --port= %d ' % self . git_port ]
if self . host == ' 127.0.0.1 ' :
cmd . append ( ' --listen= ' + self . host )
# Verify that the port is free.
if not port_is_free ( self . host , self . git_port ) :
return False
# Start the daemon.
self . gitdaemon = subprocess2 . Popen (
cmd ,
cwd = self . root_dir ,
stdout = subprocess2 . PIPE ,
stderr = subprocess2 . PIPE )
wait_for_port_to_bind ( self . host , self . git_port , self . gitdaemon )
self . populateGit ( )
self . git_dirty = Fals e
self . initialized = True
return True
def _git_rev_parse ( self , path ) :
@ -287,7 +171,7 @@ class FakeReposBase(object):
[ ' git ' , ' rev-parse ' , ' HEAD ' ] , cwd = path ) . strip ( )
def _commit_git ( self , repo , tree , base = None ) :
repo_root = join ( self . git_ root , repo )
repo_root = join ( self . git_ base , repo )
if base :
base_commit = self . git_hashes [ repo ] [ base ] [ 0 ]
subprocess2 . check_call (
@ -303,13 +187,13 @@ class FakeReposBase(object):
self . git_hashes [ repo ] . append ( ( commit_hash , new_tree ) )
def _create_ref ( self , repo , ref , revision ) :
repo_root = join ( self . git_ root , repo )
repo_root = join ( self . git_ base , repo )
subprocess2 . check_call (
[ ' git ' , ' update-ref ' , ref , self . git_hashes [ repo ] [ revision ] [ 0 ] ] ,
cwd = repo_root )
def _fast_import_git ( self , repo , data ) :
repo_root = join ( self . git_ root , repo )
repo_root = join ( self . git_ base , repo )
logging . debug ( ' %s : fast-import %s ' , repo , data )
subprocess2 . check_call (
[ ' git ' , ' fast-import ' , ' --quiet ' ] , cwd = repo_root , stdin = data . encode ( ) )
@ -952,12 +836,8 @@ class FakeReposTestBase(trial_dir.TestCase):
if not tree_root :
tree_root = self . root_dir
actual = read_tree ( tree_root )
diff = dict_diff ( tree , actual )
if diff :
logging . error ( ' Actual %s \n %s ' % ( tree_root , pprint . pformat ( actual ) ) )
logging . error ( ' Expected \n %s ' % pprint . pformat ( tree ) )
logging . error ( ' Diff \n %s ' % pprint . pformat ( diff ) )
self . assertEqual ( diff , { } )
self . assertEqual ( sorted ( tree . keys ( ) ) , sorted ( actual . keys ( ) ) )
self . assertEqual ( tree , actual )
def mangle_git_tree ( self , * args ) :
""" Creates a ' virtual directory snapshot ' to compare with the actual result
@ -967,7 +847,8 @@ class FakeReposTestBase(trial_dir.TestCase):
repo , rev = item . split ( ' @ ' , 1 )
tree = self . gittree ( repo , rev )
for k , v in tree . items ( ) :
result [ join ( new_root , k ) ] = v
path = join ( new_root , k ) . replace ( os . sep , ' / ' )
result [ path ] = v
return result
def githash ( self , repo , rev ) :