def Restore(repoPath, branchList, transaction): print("Restoring state for transaction: {tr}".format(tr=transaction)) print("branch list:") for br in branchList: print(" - Branch {br} at {hash}.{current}".format(br=br["name"], hash=br["commit"], current=' Current.' if br["is_current"] else '')) state = { "transaction": transaction, "branch_list": branchList } repo = git.open(repoPath) if repo is None: print("Failed to open git repository '{r}'".format(r=repoPath)) return 1 stateFilePath = None with tempfile.NamedTemporaryFile(mode='w+', prefix='ac2git_state_', delete=False) as stateFile: stateFilePath = stateFile.name stateFile.write(json.dumps(state)) hashObj = repo.raw_cmd(['git', 'hash-object', '-w', stateFilePath ]) if hashObj is None: raise Exception("Failed to restore state! git hash-object -w {f}, returned {r}.".format(f=stateFilePath, r=hashObj)) else: os.remove(stateFilePath) refResult = repo.raw_cmd(['git', 'update-ref', 'refs/ac2git/state', hashObj]) if refResult is None: raise Exception("Failed to restore state! git update-ref refs/ac2git/state {h}, returned {r}.".format(h=hashObj, r=refResult)) return 0
def GetBranchRevisionMap(gitRepoPath): # 1. Compare all of the different branch's commit timestamps. # 2. Select the earliest commit and iterate over commits (from all branches). # 3. Store each processed commit hash against the hash of the "tree" object to which it # points. You can get the tree hashes via the `git cat-file -p <commit-hash>` command. # 4. When processing any new commit, look up to see if the tree object has already been # cataloged in step 3. # YES -> Figure out if it makes sense for these branches to be stitched together. # It is recommended that you consider the committer, the commit time, the author # and the author time of each commit. # NO -> Continue. if git.isRepo(gitRepoPath): repo = git.open(gitRepoPath) branchList = repo.branch_list() branchRevMap = {} # For each branch in the branch list get the commit history which doesn't share # ancestry with any other branch. # See 'git rev-list' # Example command: # git rev-list --reverse my-branch ^other-branch ^another-branch for current_branch in branchList: # Get the commits that are only on this branch. revListArgs = [ current_branch.name ] for other_branch in branchList: if current_branch != other_branch: revListArgs.append('^{0}'.format(other_branch.name)) git_cmd = u'git rev-list --reverse' for arg in revListArgs: git_cmd = u'{0} {1}'.format(git_cmd, arg) cmd = git_cmd.split() try: revlist = subprocess.check_output(cmd).decode('utf8', 'strict') except subprocess.CalledProcessError as e: print(u'Failed to execute command: {0}'.format(git_cmd)) raise e #print(u'Executed: {0}'.format(git_cmd)) revlist = revlist.split() # For each of the commits returned by the git rev-list command get the tree hash # to which they point and store it in a map against the tree hash. # For each commit map it to its tree by using the git cat-file command. for rev in revlist: commit_info = CatFileCommit(rev) commit_info[u'branch'] = current_branch tree_hash = commit_info[u'object'][u'hash'] #print(u'commit: {0}, tree: {1}, branch: {2}'.format(rev, tree_hash, current_branch.name)) if not tree_hash in branchRevMap: branchRevMap[tree_hash] = [] branchRevMap[tree_hash].append(commit_info) return branchRevMap return None
def GetBranchRevisionMap(gitRepoPath): # 1. Compare all of the different branch's commit timestamps. # 2. Select the earliest commit and iterate over commits (from all branches). # 3. Store each processed commit hash against the hash of the "tree" object to which it # points. You can get the tree hashes via the `git cat-file -p <commit-hash>` command. # 4. When processing any new commit, look up to see if the tree object has already been # cataloged in step 3. # YES -> Figure out if it makes sense for these branches to be stitched together. # It is recommended that you consider the committer, the commit time, the author # and the author time of each commit. # NO -> Continue. if git.isRepo(gitRepoPath): repo = git.open(gitRepoPath) branchList = repo.branch_list() branchRevMap = {} # For each branch in the branch list get the commit history which doesn't share # ancestry with any other branch. # See 'git rev-list' # Example command: # git rev-list --reverse my-branch ^other-branch ^another-branch for current_branch in branchList: # Get the commits that are only on this branch. revListArgs = [current_branch.name] for other_branch in branchList: if current_branch != other_branch: revListArgs.append('^{0}'.format(other_branch.name)) git_cmd = u'git rev-list --reverse' for arg in revListArgs: git_cmd = u'{0} {1}'.format(git_cmd, arg) cmd = git_cmd.split() try: revlist = subprocess.check_output(git.to_utf8(c) for c in cmd) except subprocess.CalledProcessError as e: print(u'Failed to execute command: {0}'.format(git_cmd)) raise e #print(u'Executed: {0}'.format(git_cmd)) revlist = revlist.split() # For each of the commits returned by the git rev-list command get the tree hash # to which they point and store it in a map against the tree hash. # For each commit map it to its tree by using the git cat-file command. for rev in revlist: commit_info = CatFileCommit(rev) commit_info[u'branch'] = current_branch tree_hash = commit_info[u'object'][u'hash'] #print(u'commit: {0}, tree: {1}, branch: {2}'.format(rev, tree_hash, current_branch.name)) if not branchRevMap.has_key(tree_hash): branchRevMap[tree_hash] = [] branchRevMap[tree_hash].append(commit_info) return branchRevMap return None
def Restore(repoPath, branchList, transaction): print("Restoring state for transaction: {tr}".format(tr=transaction)) print("branch list:") for br in branchList: print(" - Branch {br} at {hash}.{current}".format( br=br["name"], hash=br["commit"], current=' Current.' if br["is_current"] else '')) state = {"transaction": transaction, "branch_list": branchList} repo = git.open(repoPath) if repo is None: print("Failed to open git repository '{r}'".format(r=repoPath)) return 1 stateFilePath = None with tempfile.NamedTemporaryFile(mode='w+', prefix='ac2git_state_', delete=False) as stateFile: stateFilePath = stateFile.name stateFile.write(json.dumps(state)) hashObj = repo.raw_cmd(['git', 'hash-object', '-w', stateFilePath]) if hashObj is None: raise Exception( "Failed to restore state! git hash-object -w {f}, returned {r}.". format(f=stateFilePath, r=hashObj)) else: os.remove(stateFilePath) refResult = repo.raw_cmd( ['git', 'update-ref', 'refs/ac2git/state', hashObj]) if refResult is None: raise Exception( "Failed to restore state! git update-ref refs/ac2git/state {h}, returned {r}." .format(h=hashObj, r=refResult)) return 0