From 78fdac9b5b0a1e38e8f99d3100ee9733097e49cb Mon Sep 17 00:00:00 2001 From: Chris Alfano Date: Tue, 24 Dec 2019 13:49:19 -0500 Subject: [PATCH] wip: commit additional parents from sources Issues: - Subsources of projected sources always have tree hash as head, need to figure out a way to track commit hash --- .vscode/launch.json | 17 +++++++++++------ commands/project.js | 16 +++++++++++++++- lib/Branch.js | 31 +++++++++++++++++++++++++------ lib/ParentsBag.js | 18 ++++++++++++++++++ lib/Projection.js | 15 ++++++++++----- lib/Source.js | 5 +++-- lib/index.js | 2 ++ 7 files changed, 84 insertions(+), 20 deletions(-) create mode 100644 lib/ParentsBag.js diff --git a/.vscode/launch.json b/.vscode/launch.json index b9418197..f914486c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -102,25 +102,30 @@ "name": "project", "preLaunchTask": "purge hologit studios", - "cwd": "${workspaceFolder:hologit-debug-context}", + "cwd": "${workspaceFolder:brigade-project-index}", "env": { - "DEBUG": "1" + "DEBUG": "1", + // "HOLO_CACHE_FROM": "local" }, "outputCapture": "std", "program": "${workspaceFolder:hologit}/bin/cli.js", "args": [ "project", "--working", - "--watch", + // "--watch", "--debug", // "--no-lens", - // "--fetch", + "--fetch=index-v1", // "--ref=develop", - "--commit-to=refs/holo/branch/site", + "--commit-to=gh-pages", + // "--no-cache-from", + "--cache-from=origin", + "--cache-to=origin", + "--parent-source=index-v1" // "--commit-message=foo", // holobranch - "emergence-site" + "gh-pages" ] }, { diff --git a/commands/project.js b/commands/project.js index eb489211..771d4105 100644 --- a/commands/project.js +++ b/commands/project.js @@ -33,6 +33,10 @@ exports.builder = { type: 'boolean', default: false }, + 'parent-source': { + describe: 'One or more source names to use additional parent(s) with commit-to', + type: 'string' + }, 'cache-to': { describe: 'Set a remote to push caches to', type: 'string' @@ -53,11 +57,12 @@ exports.handler = async function project ({ watch = false, commitTo = null, commitMessage = null, + parentSource = null, cacheFrom = null, cacheTo = null }) { const logger = require('../lib/logger.js'); - const { Repo, Projection } = require('../lib'); + const { Repo, Projection, ParentsBag } = require('../lib'); // check inputs @@ -111,6 +116,14 @@ exports.handler = async function project ({ } + // parse parent source + let parentsBag = null; + // TODO: append from env and split? + if (parentSource) { + parentsBag = new ParentsBag(parentSource); + } + + // load holorepo const repo = await Repo.getFromEnvironment({ ref, working }); const parentCommit = await repo.resolveRef(); @@ -137,6 +150,7 @@ exports.handler = async function project ({ commitTo, commitMessage, parentCommit, + parentsBag, fetch, cacheFrom, cacheTo diff --git a/lib/Branch.js b/lib/Branch.js index afc7e712..7cc48bc2 100644 --- a/lib/Branch.js +++ b/lib/Branch.js @@ -202,7 +202,8 @@ class Branch extends Configurable { outputTree = this.getRepo().createTree(), fetch = false, cacheFrom = null, - cacheTo = null + cacheTo = null, + parentsBag = null }) { const repo = this.getRepo(); const mappings = await this.getMappings(); @@ -216,6 +217,7 @@ class Branch extends Configurable { // load source const source = await this.workspace.getSource(holosource); + let sourceHead; if ( fetch === true @@ -223,18 +225,18 @@ class Branch extends Configurable { ) { const originalHash = await source.getHead(); await source.fetch(); - const hash = await source.getHead(); + sourceHead = await source.getHead(); const { url, ref } = await source.getCachedConfig(); - if (hash == originalHash) { - logger.info(`${source.name}@${hash.substr(0, 8)} up-to-date`); + if (sourceHead == originalHash) { + logger.info(`${source.name}@${sourceHead.substr(0, 8)} up-to-date`); } else { - logger.info(`${source.name}@${originalHash.substr(0, 8)}..${hash.substr(0, 8)} fetched ${url}#${ref}`); + logger.info(`${source.name}@${originalHash.substr(0, 8)}..${sourceHead.substr(0, 8)} fetched ${url}#${ref}`); } } // load tree - const sourceTreeHash = await source.getOutputTree({ fetch, cacheFrom, cacheTo }); + const sourceTreeHash = await source.getOutputTree({ fetch, cacheFrom, cacheTo, parentsBag }); const sourceTree = await repo.createTreeFromRef(`${sourceTreeHash}:${root == '.' ? '' : root}`); // merge source into target @@ -243,6 +245,23 @@ class Branch extends Configurable { await targetTree.merge(sourceTree, { files: files }); + + // track in parents bag + // TODO: problem -- sourceHead is always a tree hash subsources of projected source + if (parentsBag && parentsBag.sources.has(source.name)) { + const git = await repo.getGit(); + + if (!sourceHead) { + sourceHead = await source.getHead(); + } + + const type = await git.catFile(sourceHead, { t: true }); + if (type == 'tree') { + sourceHead = await git.commitTree(sourceHead, { m: `working tree for holosource: ${source.name}` }) + } + + parentsBag.commits.add(sourceHead); + } } diff --git a/lib/ParentsBag.js b/lib/ParentsBag.js new file mode 100644 index 00000000..3926733c --- /dev/null +++ b/lib/ParentsBag.js @@ -0,0 +1,18 @@ +class ParentsBag +{ + constructor (value) { + if (Array.isArray(value)) { + this.sources = new Set(value); + } else if (typeof value == 'string') { + this.sources = new Set([value]); + } else { + this.sources = new Set; + } + + this.commits = new Set; + + Object.freeze(this); + } +} + +module.exports = ParentsBag; \ No newline at end of file diff --git a/lib/Projection.js b/lib/Projection.js index 7b579755..bb77746e 100644 --- a/lib/Projection.js +++ b/lib/Projection.js @@ -14,6 +14,7 @@ class Projection { commitTo = null, commitMessage = null, parentCommit = null, + parentsBag = null, fetch = false, cacheFrom = null, cacheTo = null @@ -24,7 +25,7 @@ class Projection { // apply composition - await projection.composite({ fetch, cacheFrom, cacheTo }); + await projection.composite({ fetch, cacheFrom, cacheTo, parentsBag }); // apply lensing @@ -78,7 +79,7 @@ class Projection { commitTo = `refs/heads/${commitTo}`; } - outputHash = await projection.commit(commitTo, { parentCommit, commitMessage }); + outputHash = await projection.commit(commitTo, { parentCommit, parentsBag, commitMessage }); } @@ -101,7 +102,7 @@ class Projection { Object.freeze(this); } - async composite ({ fetch = false, cacheFrom = null, cacheTo = null }) { + async composite ({ fetch = false, cacheFrom = null, cacheTo = null, parentsBag = null }) { const branchStack = []; // merge extended holobranch onto output first @@ -124,7 +125,7 @@ class Projection { // merge projected holobranch onto output - await this.branch.composite({ outputTree: this.output.root, fetch, cacheFrom, cacheTo }); + await this.branch.composite({ outputTree: this.output.root, fetch, cacheFrom, cacheTo, parentsBag }); // strip .holo/{branches,sources} from output @@ -196,7 +197,7 @@ class Projection { } } - async commit (ref, { parentCommit=null, commitMessage = null } = {}) { + async commit (ref, { parentCommit=null, parentsBag=null, commitMessage=null } = {}) { const repo = this.branch.getRepo(); const git = await repo.getGit(); @@ -212,6 +213,10 @@ class Projection { parents.push(parentCommit); } + if (parentsBag && parentsBag.commits.size) { + parents.push(...parentsBag.commits); + } + const commitHash = await git.commitTree(await this.output.root.write(), { p: parents, m: commitMessage || `☀ projected ${this.branch.name} from ${repo.workTree || await git.describe({ always: true, tags: true }, repo.ref)}` diff --git a/lib/Source.js b/lib/Source.js index 7750804c..2cf02fd1 100644 --- a/lib/Source.js +++ b/lib/Source.js @@ -169,7 +169,7 @@ class Source extends Configurable { return treeHash; } - async getOutputTree ({ working = null, fetch = false, cacheFrom = null, cacheTo = null } = {}) { + async getOutputTree ({ working = null, fetch = false, cacheFrom = null, cacheTo = null, parentsBag = null } = {}) { const repo = this.getRepo(); const git = await repo.getGit(); const { project } = await this.getCachedConfig(); @@ -200,7 +200,8 @@ class Source extends Configurable { lens, fetch, cacheFrom, - cacheTo + cacheTo, + parentsBag }); logger.info(`using projection result for holobranch ${project.holobranch} as source ${this.name}: ${head}`); diff --git a/lib/index.js b/lib/index.js index 6b26ba76..4a170790 100644 --- a/lib/index.js +++ b/lib/index.js @@ -11,6 +11,8 @@ exports.BlobObject = require('./BlobObject.js'); exports.TreeObject = require('./TreeObject.js'); exports.SpecObject = require('./SpecObject.js'); +exports.ParentsBag = require('./ParentsBag.js'); + exports.getGit = () => { require('./logger.js').warn('hololib.getGit() is deprecated, use Git.get() instead'); return exports.Git.get();