def url_from_directory(directory, include_commit = True): with cd(directory): origin = log_check_output(['git', 'remote', 'get-url', 'origin'], universal_newlines=True)[:-1] commit = log_check_output(['git', 'log', '-1', '--format=%H'], universal_newlines=True)[:-1] ret = 'git+%s' % (origin,) if include_commit: ret += '#commit=%s' % (commit,) return ret
def actualUpdate(): with cd(self.directory): try: current_origin = log_check_output(['git', 'config', '--get', 'remote.origin.url']).strip().decode('utf-8') except CalledProcessError: current_origin = None if current_origin != self.url.geturl(): # For now we just throw a fit; it shouldn't happen often, # and in this case there's no "right" answer - the repo may # have just moved, or we may be dealing with a completely # unrelated repo. # In future, it would be nice to be a bit more interactive raise QuarkError(""" Directory '%s' is a git repository, but its remote 'origin' (%r) does not match what we expect (%r). Please either remove the local clone, or fix its remote.""" % (self.directory, current_origin, self.url.geturl())) if self.conf.get("shallow", False): # Fetch just the commit we need fork(['git', 'fetch', '--depth', '1', 'origin', self.noremote_ref()]) # Notice that we need FETCH_HEAD, as the shallow clone does not recognize # origin/HEAD & co. fork(['git', 'checkout', 'FETCH_HEAD', '--']) else: fork(['git', 'fetch']) # If we want to go on a branch, try to find a local branch that tracks it # and use it (possibly with a fast-forward) if self.ref_type == 'branch': # Resolve the remote ref remote_fullref = self.symbolic_full_name(self.ref) # Get a sensible local branch name to try local_ref = remote_fullref.split('/origin/', 1)[1] # Check if it is actually tracking our target try: local_fulltrackref = self.symbolic_full_name(local_ref + "@{u}") except CalledProcessError: # It's fine if it fails - we may not have a local-tracking branch, # so git checkout will do the right thing here local_fulltrackref = remote_fullref if remote_fullref == local_fulltrackref: try: # Checkout and fast-forward fork(['git', 'checkout', local_ref, '--']) fork(['git', 'merge', '--ff-only', self.ref, '--']) # Final sanity check if log_check_output(['git', 'rev-parse', self.ref, '--']) != log_check_output(['git', 'rev-parse', local_ref, '--']): logger.warning("Warning: your local branch is ahead of required remote branch!") return except CalledProcessError: logger.warning("Couldn't fast-forward local branch, fallback to detached head mode...") # General case: plain checkout of the origin ref (going in detached HEAD) fork(['git', 'checkout', self.ref, '--'])
def url_from_directory(directory, include_commit = True): xml = log_check_output(['svn', 'info', '--xml', directory], universal_newlines=True) doc = ElementTree.fromstring(xml) ret = doc.findall('./entry/url')[0].text if include_commit: ret += "@" + doc.findall('./entry/commit')[0].get('revision') return ret
def has_local_edit(self): xml = log_check_output(['svn', 'st', '--xml', self.directory], universal_newlines=True) doc = ElementTree.fromstring(xml) return len( doc.findall('./target/entry/wc-status[@item="modified"]')) != 0
def symbolic_full_name(self, ref): with cd(self.directory): return log_check_output( ['git', 'rev-parse', '--symbolic-full-name', ref, '--']).split(b'\n')[0].strip().decode('utf-8')
def has_local_edit(self): with cd(self.directory): return log_check_output(['git', 'status', '--porcelain']) != b""
def actualUpdate(): with cd(self.directory): try: current_origin = log_check_output( ['git', 'config', '--get', 'remote.origin.url']).strip().decode('utf-8') except CalledProcessError: current_origin = None if current_origin != self.url.geturl(): # For now we just throw a fit; it shouldn't happen often, # and in this case there's no "right" answer - the repo may # have just moved, or we may be dealing with a completely # unrelated repo. # In future, it would be nice to be a bit more interactive raise QuarkError( """ Directory '%s' is a git repository, but its remote 'origin' (%r) does not match what we expect (%r). Please either remove the local clone, or fix its remote.""" % (self.directory, current_origin, self.url.geturl())) if self.conf.get("shallow", False): # git fetch with shallow clones isn't very smart, and # re-fetches stuff that we already have; try to avoid this # FIXME: the current approach means that shallow clones # will be in detached HEAD state to a commit pretty much # always. # Probably this is not a big problem because shallow repos # in Quark aren't meant to be used for actual repo work, # and the previous implementation always had FETCH_HEAD # checked out; however, in future it would be nice to have # a cleaner solution. if self.ref_type == 'commit': # Easy case: we already know exactly the commit we need remote_commit = self.ref else: # Ask the remote what we are expected to have here remote_commit = log_check_output([ 'git', 'ls-remote', 'origin', self.noremote_ref() ]).split(b'\t')[0].strip().decode('utf-8') try: # Try to check it out; in the common case (nothing # changed) this should be a no-op fork(['git', 'checkout', remote_commit, '--']) except CalledProcessError: # Probably we don't have the commit; fetch it fork([ 'git', 'fetch', '--depth', '1', 'origin', remote_commit ]) # Try again fork(['git', 'checkout', remote_commit, '--']) else: fork(['git', 'fetch']) # If we want to go on a branch, try to find a local branch that tracks it # and use it (possibly with a fast-forward) if self.ref_type == 'branch': # Resolve the remote ref remote_fullref = self.symbolic_full_name(self.ref) # Get a sensible local branch name to try local_ref = remote_fullref.split('/origin/', 1)[1] # Check if it is actually tracking our target try: local_fulltrackref = self.symbolic_full_name( local_ref + "@{u}") except CalledProcessError: # It's fine if it fails - we may not have a local-tracking branch, # so git checkout will do the right thing here local_fulltrackref = remote_fullref if remote_fullref == local_fulltrackref: try: # Checkout and fast-forward fork(['git', 'checkout', local_ref, '--']) fork([ 'git', 'merge', '--ff-only', self.ref, '--' ]) # Final sanity check if log_check_output([ 'git', 'rev-parse', self.ref, '--' ]) != log_check_output( ['git', 'rev-parse', local_ref, '--']): logger.warning( "Warning: your local branch is ahead of required remote branch!" ) return except CalledProcessError: logger.warning( "Couldn't fast-forward local branch, fallback to detached head mode..." ) # General case: plain checkout of the origin ref (going in detached HEAD) fork(['git', 'checkout', self.ref, '--'])