Skip to content

Commit

Permalink
Add support for submodules
Browse files Browse the repository at this point in the history
  • Loading branch information
Y-- committed Oct 25, 2024
1 parent d818d26 commit 435c2b5
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 13 deletions.
16 changes: 16 additions & 0 deletions lib/helpers/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ class Context {
this.gitHubAPIPerRepo = new Map();
}

async init() {
await this._loadSubmodules();
}

async _loadSubmodules() {
this.submoduleToParentMap = new Map();
for (const repo of this.repos.slice()) {
const sg = this.getGitAPI(repo);
const submodulesInRepo = await gitHelper.getSubmodules(this.rootDir, repo);
for (const submodule of submodulesInRepo) {
this.submoduleToParentMap.set(submodule, repo);
this.repos.push(submodule);
}
}
}

getDefaultBranch(repoName) {
return this.defaultBranches.get(repoName) || this.defaultBranch;
}
Expand Down
26 changes: 14 additions & 12 deletions lib/helpers/print-results.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ module.exports = function printResults(context, startTs, res) {
}

const { pull = defaultPull, status, stash, pushed, merged, pr, state, buildStatus, buildURL, reviews } = result;
if (!status) {
if (!status || (status.isSubmodule && !status.current)) {
continue;
}

Expand All @@ -87,17 +87,17 @@ module.exports = function printResults(context, startTs, res) {
];

const branch = context.getDefaultBranch(repo);
const current = differentOrEmpty(status.current, branch);
const current = status.isSubmodule ? status.current : differentOrEmpty(status.current, branch);
let tracking = '';
if (status.tracking !== 'origin/' + status.current) {
if (!status.isSubmodule && status.tracking !== 'origin/' + status.current) {
if (status.tracking) {
tracking = status.tracking;
} else if (!context.hasDetachedHead(repo)) {
tracking = '*** none ***';
}
}

const currTxt = current + formatDiff(status) + formatDiff(status.diff_with_origin_main, true);
const currTxt = status.isSubmodule ? current : (current + formatDiff(status) + formatDiff(status.diff_with_origin_main, true));
const errorCell = error ? sanitizeErrorMessage(error) : '';
const approved = result.approved ? '✅' : '';
const hasWipCommit = result.hasWipCommit ? '🚧' : '';
Expand Down Expand Up @@ -140,6 +140,7 @@ module.exports = function printResults(context, startTs, res) {

const elapsed = new Date() - startTs;
const { repos } = context;

logger.logInfo(`Checked ${pluralizeRepos(repos.length)} in ${elapsed / 1000}s @ ${new Date().toString()}`);
logger.logInfo(`('${elapsedRange.maxRepo}' took the most time: ${elapsedRange.max}ms)`);

Expand Down Expand Up @@ -181,12 +182,12 @@ function formatElapsed(elapsedRange, elapsed) {

function formatBuildUrl(context, state, urlSpec) {
switch (state) {
case 'failure':
return colors.red(context.toPrintableUrl(urlSpec.url, urlSpec.id));
case 'pending':
return colors.yellow(context.toPrintableUrl(urlSpec.url, urlSpec.id));
case 'success':
return colors.green(context.toPrintableUrl(urlSpec.url, urlSpec.id));
case 'failure':
return colors.red(context.toPrintableUrl(urlSpec.url, urlSpec.id));
case 'pending':
return colors.yellow(context.toPrintableUrl(urlSpec.url, urlSpec.id));
case 'success':
return colors.green(context.toPrintableUrl(urlSpec.url, urlSpec.id));
}

return '';
Expand Down Expand Up @@ -368,14 +369,15 @@ function highlightSubrepos(table) {
for (const entry of table) {
const repoName = Object.keys(entry)[0];
while (prefixStack.length > 0) {
const last = prefixStack.pop() + '/';
const top = prefixStack.pop();
const last = top + '/';
if (repoName.length < last.length || !repoName.startsWith(last)) {
continue;
}

entry[' '.repeat(prefixStack.length + 1) + repoName.slice(last.length)] = entry[repoName];
delete entry[repoName];
prefixStack.push(last);
prefixStack.push(top);
break;
}

Expand Down
67 changes: 66 additions & 1 deletion lib/helpers/simple-git.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
const debug = require('debug')('pullrepo:lib:helper:simple-git');
const simpleGit = require('simple-git');
const { promises: fs } = require('fs');
const ini = require('ini');
const GitHub = require('github-api');

const EMPTY_STATUS = {
not_added: [],
conflicted: [],
created: [],
deleted: [],
ignored: undefined,
modified: [],
renamed: [],
files: [],
staged: [],
ahead: 0,
behind: 0,
current: '',
tracking: null,
detached: true,
isClean: true
};

exports.initSimpleGit = function (context, repo) {
const repoPath = context.getRepoPath(repo);
try {
Expand Down Expand Up @@ -44,6 +64,30 @@ exports.getGHRepo = async function (sg) {
};

exports.getStatus = async function (sg) {
const parentRepo = sg.context.submoduleToParentMap.get(sg.repo);
if (parentRepo) {
const status = Object.create(EMPTY_STATUS);
status.isSubmodule = true;
const parentSg = sg.context.getGitAPI(parentRepo);
const submodulePath = sg.repo.slice(parentRepo.length + 1);
const diff = await parentSg.raw(['diff', '--submodule=short', submodulePath]);
if (!diff) {
return status;
}

const diffLines = diff.split('\n');
let l = '';
for (const line of diffLines) {
if (line.startsWith('index')) {
l = line;
break;
}
}

status.current = l.split(' ')[1];
return status;
}

const status = await sg.status();
if (status.current === null && status.tracking === null) {
return await sg.status(); // Retry
Expand All @@ -55,6 +99,27 @@ exports.getStatus = async function (sg) {
return status;
};

exports.getSubmodules = async function (rootDir, repo) {
const submodules = [];
let gitmodulesStr = null;
try {
const c = await fs.readFile(`${rootDir}/${repo}/.gitmodules`);
gitmodulesStr = c.toString();
} catch (err) {
if (err.code === 'ENOENT') {
return [];
}
throw err;
}

const gitmodulesConf = await ini.parse(gitmodulesStr);
for (const { path } of Object.values(gitmodulesConf)) {
submodules.push(`${repo}/${path}`);
}

return submodules;
};

exports.updateSubmodules = async function (sg) {
await sg.raw(['submodule', 'update', '--recursive']);
};
Expand Down Expand Up @@ -82,7 +147,7 @@ async function getFullStatus(sg, defaultBranch) {
const status = await exports.getStatus(sg);
status.isDefaultBranch = status.current === defaultBranch;

if (!status.isDefaultBranch && status.current) {
if (!status.isSubmodule && !status.isDefaultBranch && status.current) {
await getDiffFromMain(sg, defaultBranch, status);
}

Expand Down
4 changes: 4 additions & 0 deletions lib/runners/pull-repo.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ const DIRTY_STATUS_KEYS = ['modified', 'deleted', 'created', 'conflicted'];

module.exports = async function doPullRepo(context, repo) {
debug.enabled && debug(`Processing repository ${repo}...`);
const isSubmodule = context.submoduleToParentMap.has(repo);
const sg = gitHelper.initSimpleGit(context, repo);
if (isSubmodule) {
return gitHelper.commonStatus(sg, repo);
}

await gitHelper.fetchAll(sg, repo, context);

Expand Down
1 change: 1 addition & 0 deletions lib/task-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const logger = require('./helpers/logger');

module.exports = async function runTask(moduleName) {
const context = new Context(appName);
await context.init();
const taskFunc = require('./runners/' + moduleName);
debug.enabled && debug(`Will process ${context.repos.join(', ')} repos in ${context.rootDir}.`);
const processor = new Processor(context, taskFunc);
Expand Down

0 comments on commit 435c2b5

Please sign in to comment.