def resolve_with(tool, repo, files): opts = {'tool': tool} paths = [repo.wjoin(f) for f in files] commands.resolve(repo.ui, repo, *paths, **opts) return True
def resolve(parent, ui, repo, files): commands.resolve(ui, repo, *files) return True
def tclose(ui, repo, *args, **opts): """ close the current topic branch and push to the central repository """ mustBeTopicRepo(repo) # Sanity check if not isClean(ui, repo): return 1 if args: branches = args else: if not onTopicBranch(ui, repo): return 1 branches = [repo.dirstate.branch()] if 'tmenu' in opts: if ui.prompt("Branch '%s': close it?" % branches[0]).upper() != 'Y': return 1 opts = { 'nopull':False, 'nopush':False } pulled = False # only pull once for branch in branches: # Pull new changes from the central repo to avoid multiple-heads problem if not opts['nopull'] and not pulled: if tryCommand(ui, "pull", lambda:commands.pull(ui, repo, **opts) >= 2): return 1 pulled = True # Can't close already closed branches, nor any of the special branches if not repo.branchheads(branch) or branch in repo.topicSpecialBranches: ui.warn("Error: %s is not an open topic branch\n" % branch) return 1 # Now update to the head of the branch being closed if repo.dirstate.parents()[0] not in repo.branchheads(branch): if tryCommand(ui, "update %s" % quoteBranch(branch), lambda:commands.update(ui, repo, node=branch)): return 1 # Unlike a normal hg commit, if no text is specified we supply a reasonable default. branch = repo.dirstate.branch() text = opts.get('message') if text is None: text = "Closing %s" % branch # Close it if tryCommand(ui, "commit --close-branch", lambda:repo.commit(text, extra = {'close':'True'}) is None): return 1 # Aditionally, for this to not be considered a "head" it has to have a # child commit. So we have to merge into prod. First, update. # if tryCommand(ui, "update %s" % repo.topicProdBranch, lambda:commands.update(ui, repo, node=repo.topicProdBranch)): return 1 # Now merge, ignoring all conflicts. mergeOpts = copy.deepcopy(opts) mergeOpts['tool'] = "internal:fail" mergeOpts['noninteractive'] = True # Ignore return value... ok if merge fails tryCommand(ui, "merge -r %s" % quoteBranch(branch), lambda:commands.merge(ui, repo, node=branch, **mergeOpts), repo = repo) # Revert all files to prod (regardless of what happened on the branch) revertOpts = copy.deepcopy(opts) revertOpts['all'] = True revertOpts['rev'] = "." if tryCommand(ui, "revert -a -r .", lambda:commands.revert(ui, repo, **revertOpts), repo = repo): return 1 # Were there any merge conflicts? resolveOpts = copy.deepcopy(opts) resolveOpts['list'] = True if tryCommand(ui, "resolve -l", lambda:commands.resolve(ui, repo, **resolveOpts), repo = repo): return 1 # Anything that had a merge conflict, mark it resolved (by the revert) if ui.lastTryCommandOutput != '': resolveOpts = copy.deepcopy(opts) resolveOpts['all'] = True resolveOpts['mark'] = True if tryCommand(ui, "resolve -a -m", lambda:commands.resolve(ui, repo, **resolveOpts), repo = repo): return 1 # Commit the merge if tryCommand(ui, "commit", lambda:repo.commit(text) is None): return 1 # And push. if not opts['nopush']: pushOpts = copy.deepcopy(opts) if 'message' in pushOpts: del pushOpts['message'] pushOpts['force'] = True nameSet = set() for name, path in ui.configitems("paths"): nameSet.add(name) if tryCommand(ui, "push -f -b %s -b %s default" % (quoteBranch(branch), repo.topicProdBranch), lambda:commands.push(ui, repo, branch=(branch,repo.topicProdBranch), **pushOpts), repo=repo) > 1: return 1 if "dev" in nameSet: if tryCommand(ui, "push -f -b %s -b %s dev" % (quoteBranch(branch), repo.topicProdBranch), lambda:commands.push(ui, repo, branch=(branch,repo.topicProdBranch), dest="dev", **pushOpts), repo=repo) > 1: return 1 if "stage" in nameSet: if tryCommand(ui, "push -f -b %s -b %s stage" % (quoteBranch(branch), repo.topicProdBranch), lambda:commands.push(ui, repo, branch=(branch,repo.topicProdBranch), dest="stage", **pushOpts), repo=repo) > 1: return 1 if "prod" in nameSet: if tryCommand(ui, "push -f -b %s -b %s prod" % (quoteBranch(branch), repo.topicProdBranch), lambda:commands.push(ui, repo, branch=(branch,repo.topicProdBranch), dest="prod", **pushOpts), repo=repo) > 1: return 1 ui.status("Done.\n")
def checkconflict(ui, repo, source=None, **opts): """Print there will be a conflict after merge or not.""" check_uncommited_changes(repo) cur_dir = repo.root local_clone_dir = cur_dir + '-local' remote_clone_dir = cur_dir + '-remote' # if the source is not specified, # we take the default one from the repo configuration. # otherwise we take source if source is None: clone_source = check_config(repo, 'default') else: is_URL = bool(urlparse.urlparse(source).netloc) if os.path.isdir(source) or is_URL: clone_source = source else: clone_source = check_config(repo, str(source)) # path to the cache list cache_dir = os.path.expanduser('~\\.hg.cache') cache_list = os.path.join(cache_dir, 'cache_list.json') # if the source is local, then just clone if hg.islocal(clone_source): clone(repo, clone_source, remote_clone_dir) # otherwise, open the cache list and see # if it contains path information to the cache # of the specified resource for the current working repo else: cache_source = None # clear the cache list if this option is set, or # if the cache list does not exist, create it if not os.path.exists(cache_list) or opts.get('clear_cache_list'): if not os.path.exists(cache_dir): make_dir(cache_dir) create_cache_list(cache_list) else: data = read_cache_list(cache_list) cache_source = find_cache_src(data, cur_dir, clone_source) # if the cache resource is found but this path does not exist or the path exists, # but it is not a repo, or set_cache_repo option, # we delete information about this cache repo from the cache list was_cached = cache_source is not None if was_cached: cache_source = cache_source.encode('cp1251') if not is_repo(repo, cache_source) or opts.get('set_cache_repo'): cache_data = read_cache_list(cache_list) new_cache_data = find_cache_src(cache_data, cur_dir, clone_source, for_remove=True) write_cache_list(cache_list, new_cache_data) repo.ui.write('\nThe last path to the cache repository is broken.\n') cache_source = None # if the cache resource is not found # suggest to choose the path to the cash repo # if the paths exists and empty -> clone, # if the path exists and repo -> checkupdate # else: select empty folder if cache_source is None: cache_source = str(raw_input('Specify the path for the cache-repository,\n' 'or if no path it will be use /user/.hg.cache path.\n')).replace('\r', '') if not cache_source: cache_source = default_cache_src(cur_dir, cache_dir) if os.path.exists(cache_source): if not os.listdir(cache_source): clone(repo, clone_source, cache_source) # clone from the resource to the cache elif is_repo(repo, cache_source): clone_root = commands.identify(repo.ui, repo, rev=0) repo = hg.repository(repo.ui, cache_source) cache_root = commands.identify(repo.ui, repo, rev=0) if clone_root == cache_root: check_update(repo, clone_source) repo = hg.repository(repo.ui, cur_dir) else: repo = hg.repository(repo.ui, cur_dir) repo.ui.write('\nCache-repo and remote-repo do not match.\n') sys.exit() else: repo.ui.write('\nYou must select an empty folder or an existing repo folder.\n') sys.exit() else: make_dir(cache_source) clone(repo, clone_source, cache_source) note = gen_note(cur_dir, clone_source, cache_source) write_cache_list(cache_list, note, add=True) # if the cache resource is found, # check if new changes can be pulled. # if yes, pull and update else: repo = hg.repository(repo.ui, cache_source) check_update(repo, clone_source) repo = hg.repository(repo.ui, cur_dir) # finally clone from cache to remote clone(repo, cache_source, remote_clone_dir) # create a local repo clone clone(repo, cur_dir, local_clone_dir) repo = hg.repository(repo.ui, remote_clone_dir) # go to remote repo clone commands.pull(repo.ui, repo, local_clone_dir) # pull changes from a local repo clone to it commands.update(repo.ui, repo) # update repo.ui.pushbuffer() conflict = do_merge(repo) deleted_str = repo.ui.popbuffer() deleted_list = re.findall('\'(.*)\'', deleted_str) # if there is a conflict, # we look at the list of files with conflicts # and display them, because merge3 will mark conflicting lines with special tags if conflict: repo.ui.pushbuffer() commands.resolve(repo.ui, repo, list=True) u_files_str = repo.ui.popbuffer() u_files_list = re.findall('U (.*)\n', u_files_str) if opts.get('check_file'): file = opts.get('check_file') if file in deleted_list: repo.ui.write( '\nfile ' + file + ' was deleted in other [merge rev] but was modified in local [working ' 'copy].\n') elif file in u_files_list: show_file_merge(repo, remote_clone_dir, file) else: repo.ui.write('\nFile ' + str(file) + ' does not cause conflict.\n' 'The conflict occurs in the following files:\n') show_all_conflicts(repo, u_files_list, deleted_list) else: show_all_conflicts(repo, u_files_list, deleted_list) repo.ui.write('\nYes, here is a conflict\n') # if there is no conflict, say it else: repo.ui.write('\nNo, everything cool\n') # go back to our work repo repo = hg.repository(repo.ui, cur_dir) # delete clones remove_clones(local_clone_dir, remote_clone_dir) sys.exit()