return Promise.map(references, reference => { return Git.Commit .lookup(reference.repo, reference.target()) .then(commit => commit.getTree()) .then(tree => { return new Promise((resolve, reject) => { const walker = tree.walk(); walker.on('entry', entry => { if(entry.isBlob()) { entry.getBlob().then( blob => reduceDocuments( documents, blob, entry, ignores, reference, name, type ) ) } }); walker.on('end', resolve); walker.on('error', reject); walker.start(); }); }) }).then(() => documents);
commitIds.map(async (commitId) => { console.log('Showing', commitId, commitIds.length); const commit = await Commit.lookup(repo, commitId); const diffs = await commit.getDiff(); diffs.map(async (diff) => { const patches = await diff.patches(); patches.map(async (patch) => { const hunks = await patch.hunks(); hunks.map(async (hunk, index) => { const lines = await hunk.lines(); const data = { hunkId: [commitId, index], commit: commit.sha(), isAdded: patch.isAdded(), isDeleted: patch.isDeleted(), isModified: patch.isModified(), context: hunk.header(), path: patch.newFile().path(), content: lines.map((line) => line.content()).join('') }; onData(data); }); }); }); });
const manipulator = co.wrap(function*(repos, maps) { const repo = repos.x; const index = yield SubmoduleUtil.getSubmoduleNames( repo); const open = yield SubmoduleUtil.listOpenSubmodules( repo); const resolvedPaths = SubmoduleUtil.resolvePaths(c.paths, index, open, true); let checkoutFromIndex; let annotated; if (c.commit === ":0") { checkoutFromIndex = true; } else { const mapped = maps.reverseCommitMap[c.commit]; annotated = yield NodeGit.Commit.lookup(repo, mapped); } yield Checkout.checkoutFiles(repo, { commit: annotated, resolvedPaths: resolvedPaths, checkoutFromIndex: checkoutFromIndex }); });
exports.fastForwardMerge = co.wrap(function *(repo, mode, commit, message) { assert.instanceOf(repo, NodeGit.Repository); assert.isNumber(mode); assert.instanceOf(commit, NodeGit.Commit); assert.isString(message); // Remember the current branch; the checkoutCommit function will move it. const branch = yield repo.getCurrentBranch(); let result = null; let newHead; if (MODE.FORCE_COMMIT !== mode) { // If we're not generating a commit, we just need to checkout the one // we're fast-forwarding to. yield Checkout.checkoutCommit(repo, commit, false); newHead = commit; } else { // Checkout the commit we're fast-forwarding to. const head = yield repo.getHeadCommit(); yield Checkout.checkoutCommit(repo, commit, false); // Then, generate a new commit that has the previous HEAD and commit to // merge as children. const sig = repo.defaultSignature(); const tree = yield commit.getTree(); const id = yield NodeGit.Commit.create( repo, 0, sig, sig, null, Commit.ensureEolOnLastLine(message), tree, 2, [head, commit]); newHead = yield repo.getCommit(id); result = newHead.id().tostrS(); // Move HEAD to point to the new commit. yield NodeGit.Reset.reset(repo, newHead, NodeGit.Reset.TYPE.HARD, null, branch.name()); } // If we were on a branch, make it current again. if (branch.isBranch()) { yield branch.setTarget(newHead, "ffwd merge"); yield repo.setHead(branch.name()); } return result; });
const makeShadowCommitForRepo = co.wrap(function *(repo, status, message, incrementTimestamp, includeUntracked, indexOnly) { assert.instanceOf(repo, NodeGit.Repository); assert.instanceOf(status, RepoStatus); assert.isString(message); assert.isBoolean(includeUntracked); assert.isBoolean(incrementTimestamp); assert.isBoolean(indexOnly); if (indexOnly) { const index = yield repo.index(); const tree = yield index.writeTree(); const sig = repo.defaultSignature(); const subCommit = yield repo.createCommit(null, sig, sig, message, tree, []); return subCommit.tostrS(); } const changes = yield TreeUtil.listWorkdirChanges(repo, status, includeUntracked); const head = yield repo.getHeadCommit(); const parents = []; const index = yield repo.index(); const treeOid = yield index.writeTree(); const indexTree = yield repo.getTree(treeOid); const newTree = yield TreeUtil.writeTree(repo, indexTree, changes); if (null !== head) { parents.push(head); const headTree = yield head.getTree(); if (newTree.id().equal(headTree.id())) { return head.sha(); } } let sig = repo.defaultSignature(); if (incrementTimestamp && null !== head) { sig = NodeGit.Signature.create(sig.name(), sig.email(), head.time() + 1, head.timeOffset()); } const id = yield NodeGit.Commit.create(repo, null, sig, sig, null, message, newTree, parents.length, parents); return id.tostrS(); });
.then(function (repo) { repos = repo; addCommand("git fetch"); addCommand("git checkout -b " + bn); var cid = remoteName[bn]; console.log("2.0 " + cid); return Git.Commit.lookup(repo, cid); })
.then(function(id) { if (mergeRequired) { // a merge commit was created, cleanup MERGE_* files in .git/ var retCode = repo.stateCleanup(); if (retCode !== git.Error.CODE.OK) { throw new Error("Internal merge cleanup failed (error code " + retCode + ")"); } } return git.Commit.lookup(repo, id); });
const writeCommit = co.wrap(function *(sha) { const commit = commits[sha]; const parents = commit.parents; // Get commit objects for parents. let parentTrees; let newParents = []; // Array of commit IDs for (let i = 0; i < parents.length; ++i) { const parent = parents[i]; if (0 === i) { parentTrees = treeCache[parent]; } const parentSha = oldCommitMap[parent]; const parentCommit = yield repo.getCommit(parentSha); newParents.push(parentCommit); } // Calculate the tree. `trees` describes the directory tree specified // by the commit at `sha` and has caches for subtrees and submodules. const trees = yield writeTree(repo, oldCommitMap, commit.changes, parentTrees); // Store the returned tree information for potential use by descendants // of this commit. treeCache[sha] = trees; // Make a commit from the tree. const commitId = yield NodeGit.Commit.create(repo, 0, sig, sig, 0, commit.message, trees.tree, newParents.length, newParents); const commitSha = commitId.tostrS(); // Store bi-directional mappings between generated and logical sha. oldCommitMap[sha] = commitSha; newCommitMap[commitSha] = sha; commitObjs[commitSha] = (yield repo.getCommit(commitSha)); return commitSha; });
const populateLibgit2MergeBugData = co.wrap(function*(repo, data) { if (data.mergeBases === undefined) { const head = data.head; const targetCommit = data.targetCommit; const mergeBases = yield GitUtil.mergeBases(repo, head, targetCommit); data.mergeBases = []; for (const base of mergeBases) { const commit = yield NodeGit.Commit.lookup(repo, base); data.mergeBases.push(commit); } } return data.mergeBases; });
const commitAndBranch = co.wrap(function *(treeId, type) { const tree = yield NodeGit.Tree.lookup(repo, treeId); const commitId = yield NodeGit.Commit.create(repo, null, sig, sig, null, type, tree, 0, []); const commit = yield repo.getCommit(commitId); yield NodeGit.Branch.create(repo, type, commit, 1); commitMap[commitId.tostrS()] = type; });
exports.writeNotes = co.wrap(function *(repo, refName, contents) { assert.instanceOf(repo, NodeGit.Repository); assert.isString(refName); assert.isObject(contents); if (0 === Object.keys(contents).length) { // Nothing to do if no contents; no point in making an empty commit or // in making clients check themselves. return; // RETURN } // We're going to directly write the tree/commit for a new note containing // `contents`. let currentTree = null; const parents = []; const ref = yield GitUtil.getReference(repo, refName); if (null !== ref) { const currentCommit = yield repo.getCommit(ref.target()); parents.push(currentCommit); currentTree = yield currentCommit.getTree(); } const odb = yield repo.odb(); const changes = {}; const ODB_BLOB = 3; const BLOB = NodeGit.TreeEntry.FILEMODE.BLOB; const writeBlob = co.wrap(function *(sha) { const content = contents[sha]; const blobId = yield odb.write(content, content.length, ODB_BLOB); const sharded = exports.shardSha(sha); changes[sharded] = new TreeUtil.Change(blobId, BLOB); }); yield DoWorkQueue.doInParallel(Object.keys(contents), writeBlob); const newTree = yield TreeUtil.writeTree(repo, currentTree, changes); const sig = yield ConfigUtil.defaultSignature(repo); const commit = yield NodeGit.Commit.create(repo, null, sig, sig, null, "git-meta updating notes", newTree, parents.length, parents); yield NodeGit.Reference.create(repo, refName, commit, 1, "updated"); });
const prepSub = co.wrap(function*(subName) { const info = {}; const subRepo = yield SubmoduleUtil.getRepo(repo, subName); info.repo = subRepo; const paths = resolvedPaths[subName]; if (options.checkoutFromIndex) { const index = yield subRepo.index(); info.index = index; // libgit2 doesn't care if requested paths don't exist, // but we do. for (const path of paths) { if (undefined === index.getByPath(path, stage)) { errors.push(noSuchFileMessage(subName, path)); } } } else { const subCommit = subCommits[subName]; const resolvedSubCommit = yield NodeGit.Commit.lookup(subRepo, subCommit); info.resolvedSubCommit = resolvedSubCommit; // libgit2 doesn't care if requested paths don't exist, // but we do. const treeId = resolvedSubCommit.treeId(); const tree = yield NodeGit.Tree.lookup(subRepo, treeId); for (const path of paths) { const entry = yield tree.entryByPath(path); if (null === entry) { errors.push(noSuchFileMessage(subName, path)); } } } submoduleInfo[subName] = info; });
exports.save = co.wrap(function *(repo, status, includeUntracked, message) { assert.instanceOf(repo, NodeGit.Repository); assert.instanceOf(status, RepoStatus); assert.isBoolean(includeUntracked); if (null !== message) { assert.isString(message); } const subResults = {}; // name to sha const subChanges = {}; // name to TreeUtil.Change const subRepos = {}; // name to submodule open repo const sig = repo.defaultSignature(); // First, we process the submodules. If a submodule is open and dirty, // we'll create the stash commits in its repo, populate `subResults` with // the `Stash.Submodule` that will be returned, `subChanges` with the sha // of the commit to be made to be used in generating the new submodule // tree, and `subRepos` to cache the open repo for each sub to be used // later. const submodules = status.submodules; yield Object.keys(submodules).map(co.wrap(function *(name) { const sub = submodules[name]; const wd = sub.workdir; if (null === wd || (wd.status.isClean() && (sub.commit === null || wd.status.headCommit === sub.commit.sha) && (!includeUntracked || 0 === Object.keys(wd.status.workdir).length))) { // Nothing to do for closed or clean subs return; // RETURN } const subRepo = yield SubmoduleUtil.getRepo(repo, name); subRepos[name] = subRepo; let stashId; if (sub.commit !== null && wd.status.headCommit === sub.commit.sha) { const FLAGS = NodeGit.Stash.FLAGS; const flags = includeUntracked ? FLAGS.INCLUDE_UNTRACKED : FLAGS.DEFAULT; stashId = yield NodeGit.Stash.save(subRepo, sig, "stash", flags); } else { stashId = NodeGit.Oid.fromString(wd.status.headCommit); } subResults[name] = stashId.tostrS(); // Record the values we've created. subChanges[name] = new TreeUtil.Change( stashId, NodeGit.TreeEntry.FILEMODE.COMMIT); })); const head = yield repo.getHeadCommit(); const headTree = yield head.getTree(); const subsTree = yield TreeUtil.writeTree(repo, headTree, subChanges); const stashId = yield NodeGit.Commit.create(repo, null, sig, sig, null, "stash", subsTree, 1, [head]); const stashSha = stashId.tostrS(); // Make synthetic-meta-ref style refs for sub-repos. yield Object.keys(subRepos).map(co.wrap(function *(name) { const sha = subResults[name]; const refName = makeSubRefName(sha); yield NodeGit.Reference.create(subRepos[name], refName, sha, 1, "sub stash"); })); // Update the stash ref and the ref log if (null === message) { message = yield exports.makeLogMessage(repo); } yield NodeGit.Reference.create(repo, metaStashRef, stashId, 1, message); yield exports.createReflogIfNeeded(repo, metaStashRef, stashSha, message); return subResults; });
.then(function(repo) { theRepo = repo; fileDir = clone.getfileDir(repo,req); return git.Commit.lookup(repo, commitId); })
.then(function(repo) { theRepo = repo; return git.Commit.lookup(repo, commitToRevert); })
.then(function(head) { theHead = head; return git.Commit.lookup(theRepo, commitToCherrypick); })
.then(function(repo) { theRepo = repo; fileDir = api.join(fileRoot, repo.workdir().substring(req.user.workspaceDir.length + 1)); return git.Commit.lookup(repo, commitId); })
exports.writeStitchedCommit = co.wrap(function *(repo, commit, subChanges, parents, keepAsSubmodule, adjustPath, skipEmpty, whitelist) { assert.instanceOf(repo, NodeGit.Repository); assert.instanceOf(commit, NodeGit.Commit); assert.isObject(subChanges); assert.isArray(parents); assert.isFunction(keepAsSubmodule); assert.isFunction(adjustPath); assert.isBoolean(skipEmpty); assert.instanceOf(whitelist, Set); let updateModules = false; // if any kept subs added or removed const changes = {}; // changes and additions let subCommits = {}; // included submodule commits const stitchSub = co.wrap(function *(name, oldName, sha) { let subCommit; try { subCommit = yield repo.getCommit(sha); } catch (e) { const metaSha = commit.id().tostrS(); if (whitelist.has(metaSha)) { return; // RETURN } throw new UserError(`\ On meta-commit ${metaSha}, ${name} is missing ${sha}. To add to allow this submodule change to be skipped, run: git notes --ref ${exports.whitelistNoteRef} add -m skip ${metaSha}`); } const subTreeId = subCommit.treeId(); changes[name] = new TreeUtil.Change(subTreeId, FILEMODE.TREE); // Now, record this submodule change as introduced by this commit, // unless it already existed in another of its parents, i.e., it was // merged in. const alreadyExisted = yield exports.sameInAnyOtherParent(repo, commit, oldName, sha); if (!alreadyExisted) { subCommits[name] = subCommit; } }); function changeKept(name, newSha) { const id = NodeGit.Oid.fromString(newSha); changes[name] = new TreeUtil.Change(id, FILEMODE.COMMIT); } for (let name in subChanges) { const mapped = adjustPath(name); if (null === mapped) { continue; // CONTINUE } const newSha = subChanges[name].newSha; changes[mapped] = null; if (keepAsSubmodule(name)) { updateModules = true; if (null !== newSha) { changeKept(name, newSha); } } else if (null !== newSha) { yield stitchSub(mapped, name, newSha); } } // If any kept submodules were added or removed, rewrite the modules // file. if (updateModules) { const newUrls = yield SubmoduleConfigUtil.getSubmodulesFromCommit(repo, commit); const content = yield exports.computeModulesFile(repo,newUrls, keepAsSubmodule, adjustPath); changes[SubmoduleConfigUtil.modulesFileName] = content; } let newCommit = null; if (!skipEmpty || 0 !== Object.keys(changes).length) { // If we've got changes or are not skipping commits, we make one. let parentTree = null; if (0 !== parents.length) { const parentCommit = parents[0]; parentTree = yield parentCommit.getTree(); } const newTree = yield TreeUtil.writeTree(repo, parentTree, changes); const commitMessage = exports.makeStitchCommitMessage(commit, subCommits); const newCommitId = yield NodeGit.Commit.create( repo, null, commit.author(), commit.committer(), commit.messageEncoding(), commitMessage, newTree, parents.length, parents); newCommit = yield repo.getCommit(newCommitId); } else if (0 !== parents.length) { // If we skip this commit, map to its parent to indicate that whenever // we see this commit in the future, substitute its parent. newCommit = parents[0]; subCommits = {}; } return { stitchedCommit: newCommit, subCommits: subCommits, }; });
.then(function(id) { return git.Commit.lookup(repo, id); });