From 49c2f163515d2130c17a6f6a6a16bc27ea69336a Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Fri, 7 Jun 2024 11:24:44 +0100 Subject: [PATCH] feat(git): Add start-revision and file arguments to `git log` --- packages/git/src/git-helpers.js | 31 ++++++++++++++++++++++++++++- packages/git/src/subcommands/log.js | 22 ++++++++++++-------- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/packages/git/src/git-helpers.js b/packages/git/src/git-helpers.js index 6c90817e..6407144b 100644 --- a/packages/git/src/git-helpers.js +++ b/packages/git/src/git-helpers.js @@ -17,7 +17,6 @@ * along with this program. If not, see . */ import path from 'path-browserify'; -import git from 'isomorphic-git'; export const PROXY_URL = 'https://cors.isomorphic-git.org'; @@ -110,3 +109,33 @@ export const determine_fetch_remote = (remote_name_or_url, remotes) => { throw new Error(`'${remote_name_or_url}' does not appear to be a git repository`); return remote_data; } + +/** + * Divide up the positional arguments into those before the `--` separator, and those after it. + * @param arg_tokens Tokens array from parseArgs({ tokens: true }) + * @returns {{before: string[], after: string[]}} + */ +export const group_positional_arguments = (arg_tokens) => { + let saw_separator = false; + const result = { + before: [], + after: [], + }; + + for (const token of arg_tokens) { + if (token.kind === 'option-terminator') { + saw_separator = true; + continue; + } + if (token.kind === 'positional') { + if (saw_separator) { + result.after.push(token.value); + } else { + result.before.push(token.value); + } + continue; + } + } + + return result; +} diff --git a/packages/git/src/subcommands/log.js b/packages/git/src/subcommands/log.js index 01bc7b02..6f14fa19 100644 --- a/packages/git/src/subcommands/log.js +++ b/packages/git/src/subcommands/log.js @@ -17,15 +17,17 @@ * along with this program. If not, see . */ import git from 'isomorphic-git'; -import { find_repo_root } from '../git-helpers.js'; +import { find_repo_root, group_positional_arguments } from '../git-helpers.js'; import { commit_formatting_options, format_commit, process_commit_formatting_options } from '../format.js'; +import { SHOW_USAGE } from '../help.js'; export default { name: 'log', - usage: 'git log [...] [--max-count ] ', + usage: 'git log [...] [--max-count ] [] [[--] ]', description: 'Show commit logs, starting at the given revision.', args: { - allowPositionals: false, + allowPositionals: true, + tokens: true, options: { ...commit_formatting_options, 'max-count': { @@ -38,23 +40,27 @@ export default { execute: async (ctx) => { const { io, fs, env, args } = ctx; const { stdout, stderr } = io; - const { options, positionals } = args; + const { options, positionals, tokens } = args; process_commit_formatting_options(options); - // TODO: Log of a specific file - // TODO: Log of a specific branch - // TODO: Log of a specific commit - const depth = Number(options['max-count']) || undefined; const { dir, gitdir } = await find_repo_root(fs, env.PWD); + const { before: refs, after: paths } = group_positional_arguments(tokens); + if (refs.length > 1 || paths.length > 1) { + stderr('error: Too many revisions or paths given. Expected [] [[--] ]'); + throw SHOW_USAGE; + } + const log = await git.log({ fs, dir, gitdir, depth, + ref: refs[0], + filepath: paths[0], }); for (const commit of log) {