Skip to content

Commit

Permalink
feat(git): Add diff display to show and log subcommands
Browse files Browse the repository at this point in the history
  • Loading branch information
AtkinsSJ authored and KernelDeimos committed Jun 28, 2024
1 parent c436460 commit 3cad1ec
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 11 deletions.
8 changes: 6 additions & 2 deletions packages/git/src/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ export const diff_formatting_options = {
* @param options Parsed command-line options.
* @returns {{raw: boolean, numstat: boolean, summary: boolean, patch: boolean, context_lines: number, no_patch: boolean, source_prefix: string, dest_prefix: string }}
*/
export const process_diff_formatting_options = (options) => {
export const process_diff_formatting_options = (options, { show_patch_by_default = true } = {}) => {
const result = {
raw: false,
numstat: false,
Expand All @@ -280,6 +280,10 @@ export const process_diff_formatting_options = (options) => {
dest_prefix: 'b/',
};

result.display_diff = () => {
return !result.no_patch && (result.raw || result.numstat || result.summary || result.patch);
};

if (options['raw'])
result.raw = true;
if (options['numstat'])
Expand Down Expand Up @@ -312,7 +316,7 @@ export const process_diff_formatting_options = (options) => {
}

// If nothing is specified, default to --patch
if (!result.raw && !result.numstat && !result.summary && !result.patch)
if (show_patch_by_default && !result.raw && !result.numstat && !result.summary && !result.patch)
result.patch = true;

// --no-patch overrides the others
Expand Down
33 changes: 31 additions & 2 deletions packages/git/src/subcommands/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,18 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import git from 'isomorphic-git';
import git, { TREE } from 'isomorphic-git';
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 {
commit_formatting_options,
diff_formatting_options,
format_commit, format_diffs,
process_commit_formatting_options,
process_diff_formatting_options,
} from '../format.js';
import path from 'path-browserify';
import { SHOW_USAGE } from '../help.js';
import { diff_git_trees } from '../diff.js';

export default {
name: 'log',
Expand All @@ -30,6 +38,7 @@ export default {
tokens: true,
options: {
...commit_formatting_options,
...diff_formatting_options,
'max-count': {
description: 'Maximum number of commits to output.',
type: 'string',
Expand All @@ -41,8 +50,10 @@ export default {
const { io, fs, env, args } = ctx;
const { stdout, stderr } = io;
const { options, positionals, tokens } = args;
const cache = {};

process_commit_formatting_options(options);
const diff_options = process_diff_formatting_options(options, { show_patch_by_default: false });

const depth = Number(options['max-count']) || undefined;

Expand All @@ -62,9 +73,27 @@ export default {
ref: refs[0],
filepath: paths[0],
});
const diff_ctx = {
fs, dir, gitdir, cache, env,
context_lines: diff_options.context_lines,
path_filters: paths.map(it => path.resolve(env.PWD, it)),
};
const read_tree = walker => walker?.content()?.then(it => new TextDecoder().decode(it));

for (const commit of log) {
stdout(format_commit(commit.commit, commit.oid, options));
if (diff_options.display_diff()) {
const diffs = await diff_git_trees({
...diff_ctx,
// NOTE: Using an empty string for a non-existent parent prevents the default value 'HEAD' getting used.
// TREE() then fails to resolve that ref, and defaults to the empty commit, which is what we want.
a_tree: TREE({ ref: commit.commit.parent[0] ?? '' }),
b_tree: TREE({ ref: commit.oid }),
read_a: read_tree,
read_b: read_tree,
});
stdout(format_diffs(diffs, diff_options));
}
}
}
}
46 changes: 39 additions & 7 deletions packages/git/src/subcommands/show.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,18 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import git from 'isomorphic-git';
import git, { TREE } from 'isomorphic-git';
import { find_repo_root } from '../git-helpers.js';
import { commit_formatting_options, process_commit_formatting_options, format_commit, format_tag, format_tree } from '../format.js';
import {
commit_formatting_options,
diff_formatting_options,
format_commit, format_diffs,
format_tag,
format_tree,
process_commit_formatting_options,
process_diff_formatting_options,
} from '../format.js';
import { diff_git_trees } from '../diff.js';

export default {
name: 'show',
Expand All @@ -28,6 +37,7 @@ export default {
allowPositionals: true,
options: {
...commit_formatting_options,
...diff_formatting_options,
},
},
execute: async (ctx) => {
Expand All @@ -36,19 +46,41 @@ export default {
const { options, positionals } = args;

process_commit_formatting_options(options);
const diff_options = process_diff_formatting_options(options);

const { dir, gitdir } = await find_repo_root(fs, env.PWD);

const objects = [...positionals];

const cache = {};
const diff_ctx = {
fs, dir, gitdir, cache, env,
context_lines: diff_options.context_lines,
path_filters: [],
};

const format_object = async (parsed_object, options) => {
const read_tree = walker => walker?.content()?.then(it => new TextDecoder().decode(it));

const format_object = async (parsed_object) => {
switch (parsed_object.type) {
case 'blob':
return parsed_object.object;
case 'commit':
return format_commit(parsed_object.object, parsed_object.oid, options);
case 'commit': {
let s = format_commit(parsed_object.object, parsed_object.oid, options);
if (diff_options.display_diff()) {
const diffs = await diff_git_trees({
...diff_ctx,
// NOTE: Using an empty string for a non-existent parent prevents the default value 'HEAD' getting used.
// TREE() then fails to resolve that ref, and defaults to the empty commit, which is what we want.
a_tree: TREE({ ref: parsed_object.object.parent[0] ?? '' }),
b_tree: TREE({ ref: parsed_object.oid }),
read_a: read_tree,
read_b: read_tree,
});
s += format_diffs(diffs, diff_options);
}
return s;
}
case 'tree':
return format_tree(parsed_object.oid, parsed_object.object, options);
case 'tag': {
Expand All @@ -64,7 +96,7 @@ export default {
format: 'parsed',
cache,
});
s += await format_object(target, options);
s += await format_object(target);
return s;
}
}
Expand All @@ -90,7 +122,7 @@ export default {
});

// Then, print it out
stdout(await format_object(parsed_object, options));
stdout(await format_object(parsed_object));
}
}
}

0 comments on commit 3cad1ec

Please sign in to comment.