mirror of
https://github.com/HeyPuter/puter
synced 2024-11-15 06:15:47 +00:00
Implement git commit
This commit is contained in:
parent
32c172d145
commit
b4e2ba4544
@ -70,3 +70,15 @@ export const find_repo_root = async (fs, pwd) => {
|
||||
|
||||
throw new Error('not a git repository (or any of the parent directories): .git');
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a shortened version of the given hash, which is still unique within the repo.
|
||||
* TODO: Ensure that whatever we produce is unique within the repo.
|
||||
* For now this is just a convenience function, so there's one place to change later.
|
||||
* @param hash
|
||||
* @returns {String} The shortened hash
|
||||
*/
|
||||
export const shorten_hash = (hash) => {
|
||||
// TODO: Ensure that whatever we produce is unique within the repo
|
||||
return hash.slice(0, 7);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
// Generated by /tools/gen.js
|
||||
import module_add from './add.js'
|
||||
import module_commit from './commit.js'
|
||||
import module_help from './help.js'
|
||||
import module_init from './init.js'
|
||||
import module_status from './status.js'
|
||||
@ -25,6 +26,7 @@ import module_version from './version.js'
|
||||
|
||||
export default {
|
||||
"add": module_add,
|
||||
"commit": module_commit,
|
||||
"help": module_help,
|
||||
"init": module_init,
|
||||
"status": module_status,
|
||||
|
114
packages/git/src/subcommands/commit.js
Normal file
114
packages/git/src/subcommands/commit.js
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Puter Technologies Inc.
|
||||
*
|
||||
* This file is part of Puter's Git client.
|
||||
*
|
||||
* Puter's Git client is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* 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 path from 'path-browserify';
|
||||
import { ErrorCodes } from '@heyputer/puter-js-common/src/PosixError.js';
|
||||
import { find_repo_root, shorten_hash } from '../git-helpers.js';
|
||||
|
||||
export default {
|
||||
name: 'commit',
|
||||
usage: 'git commit [-m|--message <message>] [-a|--author <author>]',
|
||||
description: 'Commit staged changes to the repository.',
|
||||
args: {
|
||||
allowPositionals: false,
|
||||
options: {
|
||||
message: {
|
||||
description: 'Specify the commit message',
|
||||
type: 'string',
|
||||
short: 'm',
|
||||
},
|
||||
author: {
|
||||
description: 'Specify the commit author, as `A U Thor <author@example.com>`',
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
execute: async (ctx) => {
|
||||
const { io, fs, env, args } = ctx;
|
||||
const { stdout, stderr } = io;
|
||||
const { options, positionals } = args;
|
||||
|
||||
if (!options.message) {
|
||||
// TODO: Support opening a temporary file in an editor,
|
||||
// where the user can edit the commit message if it's not specified.
|
||||
stderr('You must specify a commit message with --message or -m');
|
||||
return 1;
|
||||
}
|
||||
|
||||
const { repository_dir, git_dir } = await find_repo_root(fs, env.PWD);
|
||||
|
||||
let user_name;
|
||||
let user_email;
|
||||
|
||||
if (options.author) {
|
||||
const author_regex = /(.+?)\s+<(.+)>/;
|
||||
const matches = options.author.match(author_regex);
|
||||
if (!matches)
|
||||
throw new Error('Failed to parse author string');
|
||||
user_name = matches[1];
|
||||
user_email = matches[2];
|
||||
} else {
|
||||
user_name = await git.getConfig({
|
||||
fs,
|
||||
dir: repository_dir,
|
||||
gitdir: git_dir,
|
||||
path: 'user.name',
|
||||
});
|
||||
user_email = await git.getConfig({
|
||||
fs,
|
||||
dir: repository_dir,
|
||||
gitdir: git_dir,
|
||||
path: 'user.email',
|
||||
});
|
||||
}
|
||||
|
||||
if (!user_name || !user_email) {
|
||||
throw new Error('Missing author information. Either provide --author="A <a@b.c>" or set user.name and user.email in the git config');
|
||||
}
|
||||
|
||||
const commit_hash = await git.commit({
|
||||
fs,
|
||||
dir: repository_dir,
|
||||
gitdir: git_dir,
|
||||
message: options.message,
|
||||
author: {
|
||||
name: user_name,
|
||||
email: user_email,
|
||||
},
|
||||
});
|
||||
|
||||
const branch = await git.currentBranch({
|
||||
fs,
|
||||
dir: repository_dir,
|
||||
gitdir: git_dir,
|
||||
});
|
||||
const commit_title = options.message.split('\n')[0];
|
||||
const short_hash = shorten_hash(commit_hash);
|
||||
let output = `[${branch} ${short_hash}] ${commit_title}\n`;
|
||||
// TODO: --amend prints out the date of the original commit here, as:
|
||||
// ` Date: Fri May 17 15:45:47 2024 +0100`
|
||||
// TODO: Print out file change count, insertion count, and deletion count
|
||||
// (Seems if insertions and deletions are both 0, we should print both.
|
||||
// Otherwise we just print nonzero ones.)
|
||||
// TODO: Print out each file created or deleted. eg:
|
||||
// create mode 100644 bar
|
||||
// delete mode 100644 foo.txt
|
||||
stdout(output);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user