def cmd_set_tracking(self, track_branch): remote_pointer = StrFmt.fmt_branch_remote_pointer(track_branch.name) merge_pointer = StrFmt.fmt_branch_merge_pointer(track_branch.name) rem_name = Git.set_conf_key(self.repo.path, remote_pointer, track_branch.remote.name) longname = Git.set_conf_key(self.repo.path, merge_pointer, StrFmt.fmt_branch_longname(track_branch.name))
def cmd_set_tracking(self, track_branch): remote_pointer = StrFmt.fmt_branch_remote_pointer(track_branch.name) merge_pointer = StrFmt.fmt_branch_merge_pointer(track_branch.name) rem_name = Git.set_conf_key(self.repo.path, remote_pointer, track_branch.remote.name) longname = Git.set_conf_key( self.repo.path, merge_pointer, StrFmt.fmt_branch_longname(track_branch.name))
def cmd_compact(self, check=True): ioutils.inform('Checking for compactness: %s' % self.path) def do_check(output_always=False): is_compact, output = Git.check_compactness_local(self.path) if not is_compact or output_always: ioutils.output(output) return is_compact is_compact = do_check() if not check and not is_compact: ioutils.inform('Trying to compact', minor=True) Git.compact_local(self.path) do_check(output_always=True)
def from_checkout(cls, path): repo = GitRepo(path) names = Git.get_remotes(path) for name in names: remote = Remote(repo, name) repo.remotes[name] = remote for url in ['url', 'pushurl']: key = StrFmt.fmt_remote_key(name, url) val = Git.get_conf_key(path, key) if val: remote.urls[url] = val return repo
def detect_branches(cls, repo): for longname in Git.get_branches_remote_tracking(repo.path): if 'HEAD' in longname: # special case continue remote, name = StrFmt.split_branch_longname(longname, parts=2) remote = Remote.get_remote(repo, remote) branch = BranchRemoteTracking.get_branch(repo, remote, longname, name)
def detect_tracking(self): remote_pointer = StrFmt.fmt_branch_remote_pointer(self.name) merge_pointer = StrFmt.fmt_branch_merge_pointer(self.name) rem_name = Git.get_conf_key(self.repo.path, remote_pointer) longname = Git.get_conf_key(self.repo.path, merge_pointer) if rem_name and longname: _, _, br_name = StrFmt.split_branch_longname(longname, parts=3) remote = Remote.get_remote(self.repo, rem_name) branch = BranchRemoteTracking.get_branch(self.repo, remote, longname, br_name) branch.tracked_by = self self.tracking = branch logger.info('Detected local tracking branch %s on %s/%s' % (self.name, rem_name, br_name))
def cmd_merge(self, branch): longname = StrFmt.fmt_branch_remote_tracking(branch.remote.name, branch.name) if Git.commit_is_ahead_of(self.repo.path, self.name, longname): ioutils.suggest('Branch %s is ahead of %s, is pushable' % (self.name, longname), minor=True) return True else: if self.cmd_checkout(): remoted = StrFmt.fmt_branch_remote_tracking(branch.remote.name, branch.name) merge_ok, output = Git.merge(self.repo.path, remoted) if merge_ok: if output: ioutils.inform('Merged %s on %s' % (longname, self.name), minor=True) ioutils.output(output) return True else: Git.reset_hard(self.repo.path, self.name)
def detect_branches(cls, repo): found = [] for name in Git.get_branches_local(repo.path): branch = BranchLocal.get_branch(repo, name) branch.exists = True found.append(name) for name in repo.branches: if not name in found: repo.branches[name].exists = False
def merge_local_tracking_branches(self): logger.info('Merging local tracking branches') save_commit = Git.get_checked_out_commit(self.path) # checkout current branch in case repo has just been cloned and workdir # is empty if not Git.repo_is_clean(self.path): if save_commit in self.branches: self.branches[save_commit].cmd_checkout() stashed = False if not Git.repo_is_clean(self.path): if Git.stash(self.path): ioutils.inform('Repo is dirty, stashed at %s' % save_commit, minor=True) stashed = True for branch in self.branches.values(): if branch.tracking: if not branch.cmd_merge(branch.tracking): ioutils.complain('Merge failed at %s of %s/%s' % (branch.name, branch.tracking.remote.name, branch.tracking.name), minor=True) if Git.checkout(self.path, save_commit): if stashed and Git.stash(self.path, apply=True): ioutils.inform('Restored stash at %s' % save_commit, minor=True)
def cmd_merge(self, branch): longname = StrFmt.fmt_branch_remote_tracking(branch.remote.name, branch.name) if Git.commit_is_ahead_of(self.repo.path, self.name, longname): ioutils.suggest('Branch %s is ahead of %s, is pushable' % (self.name, longname), minor=True) return True else: if self.cmd_checkout(): remoted = StrFmt.fmt_branch_remote_tracking( branch.remote.name, branch.name) merge_ok, output = Git.merge(self.repo.path, remoted) if merge_ok: if output: ioutils.inform('Merged %s on %s' % (longname, self.name), minor=True) ioutils.output(output) return True else: Git.reset_hard(self.repo.path, self.name)
def set_remotes_in_checkout(self): logger.info('Setting remotes in checkout') # remove remotes not in model remotes_names = Git.get_remotes(self.path) names = filter(lambda n: n not in self.remotes, remotes_names) for name in names: Git.remove_remote(self.path, name) # add remotes not in checkout names = filter(lambda n: n not in remotes_names, self.remotes.keys()) for name in names: Git.add_remote(self.path, name, self.remotes[name].urls['url']) # overwrite urls in checkout for remote in self.remotes.values(): for key, val in remote.urls.items(): key = StrFmt.fmt_remote_key(remote.name, key) Git.set_conf_key(self.path, key, val)
def merge_local_tracking_branches(self): logger.info('Merging local tracking branches') save_commit = Git.get_checked_out_commit(self.path) if save_commit is None: ioutils.complain('Failed to get last commit for %s' % self.path) return # checkout current branch in case repo has just been cloned and workdir # is empty if not Git.repo_is_clean(self.path): if save_commit in self.branches: self.branches[save_commit].cmd_checkout() # if the workdir is not clean we will stash it first stashed = False if not Git.repo_is_clean(self.path): if Git.stash(self.path): ioutils.inform('Repo is dirty, stashed at %s' % save_commit, minor=True) stashed = True # merge all tracking branches for branch in self.branches.values(): if branch.tracking: if not branch.cmd_merge(branch.tracking): ioutils.complain('Merge failed at %s of %s/%s' % (branch.name, branch.tracking.remote.name, branch.tracking.name), minor=True) # check out the "current branch" again - so we end on the same branch # checked out as we had in the beginning if save_commit in self.branches: self.branches[save_commit].cmd_checkout() # apply the stash back onto the workdir (could create a conflict) if Git.checkout(self.path, save_commit): if stashed and Git.stash(self.path, apply=True): ioutils.inform('Restored stash at %s' % save_commit, minor=True)
def do_init_repo(self): logger.info('Initializing repo') os.makedirs(self.path) Git.repo_init(self.path) self.set_remotes_in_checkout()
def cmd_fetch(self): return Git.fetch(self.repo.path, self.name)
def check_exists(self): found = False for name in Git.get_branches_local(self.repo.path): if self.name == name: found = True self.exists = found
def do_check(output_always=False): is_compact, output = Git.check_compactness_local(self.path) if not is_compact or output_always: ioutils.output(output) return is_compact
def cmd_checkout(self): if Git.checkout(self.repo.path, self.name): return True
def cmd_add_tracking(cls, repo, track_branch): if Git.add_local_tracking_branch(repo.path, track_branch.remote.name, track_branch.name): branch = cls.get_branch(repo, track_branch.name) branch.tracking = track_branch
def is_checked_out(self): return self.name == Git.get_checked_out_commit(self.repo.path)
def check_exists(self): found = False for longname in Git.get_branches_remote_tracking(self.repo.path): if self.longname == longname: found = True self.exists = found
def cmd_remove(self): if Git.remove_local_branch(self.repo.path, self.name): if self.tracking: self.tracking.tracked_by = None del (self.repo.branches[self.name])
def cmd_remove(self): if Git.remove_local_branch(self.repo.path, self.name): if self.tracking: self.tracking.tracked_by = None del(self.repo.branches[self.name])