Skip to content

Commit 28f72cd

Browse files
committed
Implement git show
1 parent 084086e commit 28f72cd

File tree

3 files changed

+135
-0
lines changed

3 files changed

+135
-0
lines changed

packages/git/src/format.js

+37
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,40 @@ export const format_commit = (commit, oid, options = {}) => {
175175
}
176176
}
177177
}
178+
179+
/**
180+
* Produce a string representation of a tree.
181+
* @param oid
182+
* @param tree
183+
* @param options
184+
* @returns {string}
185+
*/
186+
export const format_tree = (oid, tree, options = {}) => {
187+
let s = '';
188+
s += `tree ${oid}\n`;
189+
s += '\n';
190+
for (const tree_entry of tree) {
191+
s += `${tree_entry.path}\n`;
192+
}
193+
s += '\n';
194+
return s;
195+
}
196+
197+
/**
198+
* Produce a string representation of a tag.
199+
* Note that this only includes the tag itself, and not the tag's target,
200+
* which must be separately retrieved and formatted.
201+
* @param tag
202+
* @param options
203+
* @returns {string}
204+
*/
205+
export const format_tag = (tag, options = {}) => {
206+
let s = '';
207+
s += `tag ${tag.tag}\n`;
208+
s += `Tagger: ${format_person(tag.tagger)}\n`;
209+
s += `Date: ${format_date(tag.tagger, options)}\n`;
210+
if (tag.message) {
211+
s += `\n${tag.message}\n\n`;
212+
}
213+
return s;
214+
}

packages/git/src/subcommands/__exports__.js

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import module_config from './config.js'
2323
import module_help from './help.js'
2424
import module_init from './init.js'
2525
import module_log from './log.js'
26+
import module_show from './show.js'
2627
import module_status from './status.js'
2728
import module_version from './version.js'
2829

@@ -33,6 +34,7 @@ export default {
3334
"help": module_help,
3435
"init": module_init,
3536
"log": module_log,
37+
"show": module_show,
3638
"status": module_status,
3739
"version": module_version,
3840
};

packages/git/src/subcommands/show.js

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (C) 2024 Puter Technologies Inc.
3+
*
4+
* This file is part of Puter's Git client.
5+
*
6+
* Puter's Git client is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published
8+
* by the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
import git from 'isomorphic-git';
20+
import { find_repo_root } from '../git-helpers.js';
21+
import { commit_formatting_options, process_commit_formatting_options, format_commit, format_tag, format_tree } from '../format.js';
22+
23+
export default {
24+
name: 'show',
25+
usage: 'git show [<formatting-option>...] <object>',
26+
description: 'Show information about an object (commit, tree, tag, blob, etc.) in git.',
27+
args: {
28+
allowPositionals: true,
29+
options: {
30+
...commit_formatting_options,
31+
},
32+
},
33+
execute: async (ctx) => {
34+
const { io, fs, env, args } = ctx;
35+
const { stdout, stderr } = io;
36+
const { options, positionals } = args;
37+
38+
process_commit_formatting_options(options);
39+
40+
const { repository_dir, git_dir } = await find_repo_root(fs, env.PWD);
41+
42+
const objects = [...positionals];
43+
44+
const cache = {};
45+
46+
const format_object = async (parsed_object, options) => {
47+
switch (parsed_object.type) {
48+
case 'blob':
49+
return parsed_object.object;
50+
case 'commit':
51+
return format_commit(parsed_object.object, parsed_object.oid, options);
52+
case 'tree':
53+
return format_tree(parsed_object.oid, parsed_object.object, options);
54+
case 'tag': {
55+
const tag = parsed_object.object;
56+
let s = format_tag(tag, options);
57+
// Formatting a tag also outputs the formatted object it points to.
58+
// That may also be a tag, so we recurse.
59+
const target = await git.readObject({
60+
fs,
61+
dir: repository_dir,
62+
gitdir: git_dir,
63+
oid: tag.object,
64+
format: 'parsed',
65+
cache,
66+
});
67+
s += await format_object(target, options);
68+
return s;
69+
}
70+
}
71+
}
72+
73+
for (const ref of objects) {
74+
// Could be any ref, so first get the oid that's referred to.
75+
const oid = await git.resolveRef({
76+
fs,
77+
dir: repository_dir,
78+
gitdir: git_dir,
79+
ref,
80+
});
81+
82+
// Then obtain the object and parse it.
83+
const parsed_object = await git.readObject({
84+
fs,
85+
dir: repository_dir,
86+
gitdir: git_dir,
87+
oid,
88+
format: 'parsed',
89+
cache,
90+
});
91+
92+
// Then, print it out
93+
stdout(await format_object(parsed_object, options));
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)