def diff_limb(): options = config["options"] limb1name = config["limb1"].rstrip("/") limb2name = config["limb2"].rstrip("/") paths = config["paths"] if not limb1name: limb1name = git.current_limb().name if not limb2name: limb2name = git.current_limb().name limb1 = git.Limb.get(limb1name) if not limb1.exists(): sys.stdout.write("%s: not found\n" % limb1name) sys.exit(1) limb2 = git.Limb.get(limb2name) if not limb2.exists(): sys.stdout.write("%s: not found\n" % limb2name) sys.exit(1) limb1_subnames = git.subnames(limb1name) limb2_subnames = git.subnames(limb2name) not_found = False diff_branches = [] for subname in sorted(set(limb1_subnames + limb2_subnames)): branch1name = "%s/%s" % (limb1name, subname) branch2name = "%s/%s" % (limb2name, subname) if subname not in limb1_subnames: sys.stdout.write("WARNING, non-existent branch: %s\n" % branch1name) not_found = True continue if subname not in limb2_subnames: sys.stdout.write("WARNING, non-existent branch: %s\n" % branch2name) not_found = True continue branch1 = git.Branch.get(branch1name) branch2 = git.Branch.get(branch2name) if branch1.id == branch2.id: continue diff_branches.append([branch1name, branch2name]) if not_found and diff_branches: sys.stdout.write("\n") for branch1name, branch2name in diff_branches: cmd = ['git', '--no-pager', 'diff'] + options cmd.append('%s..%s' % (branch1name, branch2name)) cmd += paths git.call(cmd, stdout=sys.stdout, verbose=True)
def signoff_limb(): options = config["options"] limb1name = config["limb1"].rstrip("/") limb2name = config["limb2"].rstrip("/") if not limb2name: limb2name = git.current_limb().name limb1 = git.Limb.get(limb1name) if not limb1.exists(): sys.stdout.write("%s: not found\n" % limb1name) sys.exit(1) limb2 = git.Limb.get(limb2name) if not limb2.exists(): sys.stdout.write("%s: not found\n" % limb2name) sys.exit(1) limb1_subnames = git.subnames(limb1name) limb2_subnames = git.subnames(limb2name) signed_off_count = 0 skipped_branchnames = [] for subname in limb2_subnames: limb1_branchname = "%s/%s" % (limb1name, subname) limb2_branchname = "%s/%s" % (limb2name, subname) if subname.startswith("external."): continue if subname not in limb1_subnames: skipped_branchnames.append((limb1_branchname, limb2_branchname)) continue limb1_branch = git.Branch.get(limb1_branchname) limb2_branch = git.Branch.get(limb2_branchname) if limb1_branch.id == limb2_branch.id: continue cmd = ['git', 'checkout', limb2_branchname] git.call(cmd, stdout=sys.stdout, verbose=True) cmd = ['git', 'signoff-mv'] + options + ['%s..' % limb1_branchname] # ignore the error return from git signoff-mv, until it's fixed git.call(cmd, error=None, stdout=sys.stdout, stderr=sys.stderr, verbose=True) signed_off_count += 1 for limb1_branchname, limb2_branchname in skipped_branchnames: sys.stdout.write("%s not found, \n" % limb1_branchname) sys.stdout.write(" NOT signing off on commits in %s\n" % limb2_branchname) else: if not signed_off_count: sys.stdout.write("No new commits to signoff.\n")
def git_ls_limb(): limbname = config["limb"] recursive = config["recursive"] if limbname == None: limbname = git.current_limb().name else: limbname = limbname.strip("/") if limbname: limb = git.Limb.get(limbname) if not limb or not limb.exists(): sys.stderr.write("%s: limb not found\n" % limbname) sys.exit(1) branches = True limbs = True if config["branches-only"]: limbs = False elif config["limbs-only"]: branches = False if limbs and limbname: sys.stdout.write("%s/\n" % limbname) for name in git.branchnames(limbname, recursive=recursive, branches=branches, limbs=limbs): sys.stdout.write("%s\n" % name)
def git_pending_limb(): verbose = config["verbose"] limb = config["left"] if limb: limb = git.Limb.get(limb) else: limb = git.current_limb() total_changes = 0 for branch in limb.repository_branches: if not verbose: if 'frozen' in branch.flags: continue if 'deferred' in branch.flags: continue for prov in branch.providers: prov = valid_provider(branch, prov) if change_count(prov, branch) or recursive_change_count(prov): break else: continue branch_changes = git_pending_branch(branch) total_changes += branch_changes if branch_changes and branch != limb.repository_branches[-1]: sys.stdout.write("\n") if not total_changes: sys.stdout.write("No pending changes in %s/\n" % limb.name)
def git_list_dependencies(): limbname = config["limb1"] if not limbname: limbname = git.current_limb().name branch_dep_ref = "%s/limb-info:MONTAVISTA/branch_dependencies" % limbname try: git.call(['git', 'show', branch_dep_ref], stdout=sys.stdout) except: sys.stderr.write("%s not found\n", branch_dep_ref) sys.exit(1)
def git_list_branches(): branch_name = git.current_branch().name limb_name = git.current_limb().name if limb_name: sys.stdout.write("%s/\n" % limb_name) for name in git.branchnames(limb_name): if name == branch_name: sys.stdout.write("* %s\n" % name) else: sys.stdout.write(" %s\n" % name)
def git_dependent_branches(): provider = config["dependents"].strip('/') if provider: provider = git.Branch(provider) else: provider = git.current_branch() limbs = config["limbs"] if limbs: limbs = [git.Limb.get(x.strip('/')) for x in limbs] else: limbs = [git.current_limb()] for limb in limbs: for branch in provider.all_dependents(limb): sys.stdout.write('%s\n' % branch.name)
def git_move_limb(): force = config["force"] recursive = config["recursive"] if config["limb2"]: oldlimbname = config["limb1"] newlimbname = config["limb2"] else: oldlimbname = git.current_limb().name newlimbname = config["limb1"] oldlimb = git.Limb.get(oldlimbname) if not oldlimb.exists(): if not oldlimbname: oldlimbname = '""' sys.stderr.write("%s: not found\n" % oldlimbname) sys.exit(1) newlimb = git.Limb.get(newlimbname) if newlimb.exists(): if force: cmd = ['git', 'branch', '-D'] cmd += git.branchnames(newlimbname, recursive=recursive) git.call(cmd, stdout=sys.stdout) else: sys.stderr.write("%s: already exists. Use -M to overwrite.\n" % newlimbname) sys.exit(1) if force: m_opt = "M" else: m_opt = "m" branchnames = git.branchnames(oldlimbname, recursive=recursive) subnames = [x[(len(oldlimbname) + 1):] for x in branchnames] for subname in subnames: old_name = "%s/%s" % (oldlimbname, subname) new_name = "%s/%s" % (newlimbname, subname) cmd = ['git', 'branch', '-%s' % m_opt, old_name, new_name] git.call(cmd, stdout=sys.stdout, verbose=True)
def log_limbs(): options = config["options"] separator = config["separator"] limb1name = config["limb1"].rstrip("/") limb2name = config["limb2"].rstrip("/") paths = config["paths"] if not limb1name: limb1name = git.current_limb().name if not separator: for option in options: if option.startswith("--max-count"): break else: options.append("--max-count=1") been_here = False limb1 = git.branchnames(limb1name) for branchname in git.branchnames(limb1name): cmd = ['git', '--no-pager', 'log'] + options cmd.append(branchname) cmd += paths if been_here: sys.stdout.write("\n") else: been_here = True git.call(cmd, stdout=sys.stdout, verbose=True) sys.exit(0) if not limb2name: limb2name = git.current_limb().name limb1 = git.Limb.get(limb1name) if not limb1.exists(): sys.stdout.write("%s: not found\n" % limb1name) sys.exit(1) limb2 = git.Limb.get(limb2name) if not limb2.exists(): sys.stdout.write("%s: not found\n" % limb2name) sys.exit(1) limb1_subnames = git.subnames(limb1name) limb2_subnames = git.subnames(limb2name) not_found = False log_branches = [] for subname in sorted(set(limb1_subnames + limb2_subnames)): branch1name = "%s/%s" % (limb1name, subname) branch2name = "%s/%s" % (limb2name, subname) if subname not in limb1_subnames: sys.stdout.write("WARNING, non-existent branch: %s\n" % branch1name) not_found = True continue if subname not in limb2_subnames: sys.stdout.write("WARNING, non-existent branch %s\n" % branch2name) not_found = True continue branch1 = git.Branch.get(branch1name) branch2 = git.Branch.get(branch2name) if branch1.id == branch2.id: continue log_branches.append([branch1name, branch2name]) if not_found and log_branches: sys.stdout.write("\n") been_here = False for branch1name, branch2name in log_branches: range = "%s%s%s" % (branch1name, separator, branch2name) cmd = ['git', 'rev-list'] + [range] + paths if not bool(git.call(cmd)): continue if been_here: sys.stdout.write("\n") else: been_here = True cmd = ['git', '--no-pager', 'log'] + options + [range] + paths git.call(cmd, stdout=sys.stdout, verbose=True)
def push_limb(): re_parent = re.compile(r'(.*)/bugfixes/\d+[^/]*') options = config["options"] repo = config["repo"] localname = config["local"].rstrip("/") remotename = config["remote"].rstrip("/") nofetch = config["nofetch"] if not remotename: if not localname: localname = git.current_limb().name remotename = localname if not localname or not nofetch: git.call(['git', 'fetch', repo], stdout=sys.stdout, verbose=True) git.call(['git', 'remote', 'prune', repo], stdout=sys.stdout, verbose=True) if not localname: remote_branchnames = git.branchnames("%s/%s" % (repo, remotename)) if not remote_branchnames: sys.stdout.write("remote limb %s not found\n" % remotename) sys.exit(1) del_prefix_len = len(repo) + 1 cmd = ['git', 'push'] + options + [repo] cmd += [":%s" % x[del_prefix_len:] for x in remote_branchnames] git.call(cmd, stdout=sys.stdout, verbose=True) return local = git.Limb.get(localname) if not local.exists(): sys.stdout.write("local limb %s not found\n" % localname) sys.exit(1) if not nofetch: # call "git analyze-changes" before pushing cmd = ['git', 'analyze-changes', '-r', repo] if local != git.current_limb(): cmd.append(localname) try: git.call(cmd, stdout=sys.stdout, verbose=True) except: sys.stderr.write( "git analyze-changes failed. No branches pushed.\n") sys.exit(1) time.sleep(5) local_subnames = git.subnames(localname) nff_names = [] rebased_names = [] branchnames = [] for subname in local_subnames: branchname = "%s/%s" % (localname, subname) repo_branchname = "%s/%s/%s" % (repo, remotename, subname) repo_branch = git.Branch.get(repo_branchname) branch = git.Branch.get(branchname) if repo_branch.id and repo_branch.id == branch.id: continue rebased = False match = re_parent.match(remotename) if match: parentname = match.group(1) parent_branchname = "%s/%s/%s" % (repo, parentname, subname) parent_branch = git.Branch.get(parent_branchname) rebased = parent_branch.id and not branch.contains(parent_branch) if rebased: rebased_names.append(branchname) elif repo_branch.id and not branch.contains(repo_branch): nff_names.append(branchname) if localname != remotename: branchname = "%s:%s" % (branchname, "%s/%s" % (remotename, subname)) branchnames.append(branchname) force = "-f" in options or "--force" in options if rebased_names and not force: parentname = "%s/%s" % (repo, parentname) sys.stdout.write("\nNon-fast-forward when compared to %s:\n" % parentname) for branchname in rebased_names: sys.stdout.write(" %s\n" % branchname) sys.stdout.write('\nPlease do "git rebase-limb %s".\n' % parentname) sys.stdout.write("Or if this is what you want, " "re-push the limb using --force.\n") sys.stdout.write("\nNo branches pushed.\n") return if nff_names and not force: sys.stdout.write("\nNon-fast-forward:\n") for branchname in nff_names: sys.stdout.write(" %s\n" % branchname) sys.stdout.write("\nIf this is what you want, " "re-push the limb using --force.\n") sys.stdout.write("\nNo branches pushed.\n") return if not branchnames: sys.stdout.write("No updated or new branches to push.\n") return cmd = ['git', 'push'] + options + [repo] + branchnames git.call(cmd, stdout=sys.stdout, verbose=True)
def git_create_limb(): limb1name = config["limb1"] limb2name = config["limb2"] force = config["force"] recursive = config["recursive"] checkout = config["checkout"] checkout_name = None if checkout: check_clean_state() branch = git.Branch.get(limb1name) if branch.exists(): sys.stdout.write("%s is an existing branch, need a limb name\n" % limb1name) sys.exit(1) remote = git.remote_alias() if limb1name.startswith(remote + '/'): sys.stdout.write('%s: Cannot create a limb beginning with "%s"\n' % (limb1name, remote)) sys.exit(1) if limb2name: branch = git.Branch.get(limb2name) if branch.exists(): sys.stdout.write("%s is an existing branch, need a limb\n" % limb2name) sys.exit(1) limb2 = git.Limb.get(limb2name) else: limb2 = git.current_limb() limb2name = limb2.name if not limb2.exists(): if not limb2name: limb2name = '""' sys.stdout.write("%s: not found\n" % limb2name) sys.exit(1) if limb1name == limb2name: sys.stdout.write("%s and %s are identical.\n" % (limb1name, limb2name)) return limb1_branchnames = git.branchnames(limb1name, recursive=recursive) if limb1_branchnames and not force: sys.stderr.write("%s exists. Use -f to force overwrite.\n" % limb1name) sys.exit(1) limb2_subnames = git.subnames(limb2name, recursive=recursive) try: current = git.current_branch() current_name = current.name except: current_name = None if current_name and current_name in limb1_branchnames: if not checkout: check_clean_state() git.call(['git', 'checkout', current.id], stdout=None, stderr=None) checkout = True if current.subname in limb2_subnames: checkout_name = current_name limb1_subnames = git.subnames(limb1name, limb1_branchnames) for subname in limb2_subnames: destname = "%s/%s" % (limb1name, subname) sourcename = "%s/%s" % (limb2name, subname) dest = git.Branch.get(destname) source = git.Branch.get(sourcename) if dest.id != source.id: cmd = ['git', 'branch', '-f', destname, sourcename] git.call(cmd, stdout=sys.stdout, verbose=True) if not checkout_name: checkout_name = destname for subname in limb1_subnames: if subname in limb2_subnames: continue del_name = "%s/%s" % (limb1name, subname) cmd = ['git', 'branch', '-D', del_name] git.call(cmd, stdout=sys.stdout, verbose=True) if checkout: if not checkout_name: sys.stderr.write("No branch in %s to checkout.\n" % limb2name) sys.exit(1) cmd = ['git', 'checkout', checkout_name] if current_name and checkout_name == current.name: git.call(cmd, stdout=None, stderr=None) else: git.call(cmd, stdout=sys.stdout, verbose=True)
def rebase_limb(): options = config["options"] upstreamname = config["upstream"] limbname = config["limb"] if limbname: common_branch = "%s/common" % limbname.rstrip("/") cmd = ['git', 'checkout', common_branch] git.call(cmd, stdout=sys.stdout, verbose=True) original_branch = git.current_branch() limb = git.current_limb() limbname = limb.name upstreamname = upstreamname.rstrip("/") upstream = git.Limb.get(upstreamname) if not limb.exists(): sys.stdout.write("%s: not found\n" % limbname) sys.exit(1) if not upstream.exists(): sys.stdout.write("%s: not found\n" % upstreamname) sys.exit(1) upstream_subnames = git.subnames(upstreamname) limb_subnames = git.subnames(limbname) not_rebased = [] for subname in limb_subnames: limb_branchname = "%s/%s" % (limbname, subname) upstream_branchname = "%s/%s" % (upstreamname, subname) if subname not in upstream_subnames: not_rebased.append((limb_branchname, upstream_branchname)) continue limb_branch = git.Branch.get(limb_branchname) upstream_branch = git.Branch.get(upstream_branchname) if limb_branch.contains(upstream_branch): continue cmd = ['git', 'checkout', limb_branchname] git.call(cmd, stdout=sys.stdout, verbose=True) cmd = ['git', 'rebase'] + options + [upstream_branchname] git.call(cmd, stdout=sys.stdout, verbose=True) for subname in upstream_subnames: if subname in limb_subnames: continue limb_branchname = "%s/%s" % (limbname, subname) upstream_branchname = "%s/%s" % (upstreamname, subname) cmd = ['git', 'branch', limb_branchname, upstream_branchname] git.call(cmd, stdout=sys.stdout, verbose=True) # restore original branch if git.current_branch() != original_branch: cmd = ['git', 'checkout', original_branch.name] git.call(cmd, stdout=sys.stdout, verbose=True) if not_rebased: sys.stderr.write("\n") for limb_branchname, upstream_branchname in not_rebased: sys.stderr.write("NOT rebasing %s, no %s\n" % (limb_branchname, upstream_branchname))
if len(args) > 0: arg0 = args[0] match = (re.match(r'(.*)(\.\.\.)(.*)', arg0) or re.match(r'(.*)(\.\.)(.*)', arg0)) else: arg0 = '' match = None if not remote_alias: remote_alias = git.remote_alias() if match: limb1_name, separator, limb2_name = match.groups() if not limb1_name: limb1_name = git.current_limb().name if not limb2_name: limb2_name = git.current_limb().name else: limb2_name = arg0 if not limb2_name: limb2_name = git.current_limb().name limb1_name = limb2_name remote_prefix = '%s/' % remote_alias if limb1_name.startswith('/'): limb1_name = limb1_name[1:] if limb1_name.startswith(remote_prefix): limb1_name = limb1_name[len(remote_prefix):] limb1_name = '%s/%s' % (remote_alias, limb1_name) separator = '..'
return def do_sub_repos(r): for v in sub_repos: if r[0].startswith(v[0]): r[0] = r[0].replace(v[0], v[1], 1) break return r process_options() branches = config["branches"] sub_repos = config["sub-repos"] limb = git.current_limb() depfile = git_call_with_err(['git', 'show', limb.name + "/limb-info:MONTAVISTA/branch_dependencies" ], "Error opening branch dependency file for " + limb.name) deplines = depfile.split("\n") for i in range(1, len(deplines)): branch = extern_branch(deplines[i]) if branch is None: continue src = get_source(deplines[i - 1]) if src is None: continue branch = limb.name + "/" + branch
def merge_limb(): options = config["options"] remotename = config["remote"] limbname = config["limb"] if limbname: limbname = limbname.rstrip('/') limb = git.Limb.get(limbname) branch = limb.repository_branches()[0] git.call(['git', 'checkout', branch], stdout=sys.stdout, verbose=True) else: limb = git.current_limb() limbname = limb.name remote = git.Limb.get(remotename) remotename = remote.name.rstrip("/") if not limb.exists(): sys.stdout.write("%s: not found\n" % limbname) sys.exit(1) if not remote.exists(): sys.stdout.write("%s: not found\n" % remotename) sys.exit(1) limb_subnames = git.subnames(limbname) remote_subnames = git.subnames(remotename) for subname in remote_subnames: if subname not in limb_subnames: limb_branchname = "%s/%s" % (limbname, subname) remote_branchname = "%s/%s" % (remotename, subname) cmd = ['git', 'branch', limb_branchname, remote_branchname] git.call(cmd, stdout=sys.stdout, verbose=True) for subname in limb_subnames: if subname not in remote_subnames: continue limb_branchname = "%s/%s" % (limbname, subname) remote_branchname = "%s/%s" % (remotename, subname) limb_branch = git.Branch.get(limb_branchname) remote_branch = git.Branch.get(remote_branchname) if limb_branch.contains(remote_branch): sys.stdout.write("%s is up-to-date.\n" % limb_branchname) continue try: cmd = ['git', 'checkout', limb_branchname] git.call(cmd, stdout=sys.stdout, verbose=True) cmd = ['git', 'merge', remote_branchname] git.call(cmd, stdout=sys.stdout, verbose=True) except git.GitError: cmdline = ' '.join([re.sub(".*/", "", sys.argv[0])] + sys.argv[1:]) sys.stdout.write("\n") sys.stdout.write("After resolving this issue, you may continue\n") sys.stdout.write("the merge by re-running the command:\n") sys.stdout.write(" %s\n" % cmdline) if config["debug"]: sys.stdout.write("\n") raise sys.exit(1)