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 path from 'path-browserify' ;
21
+ import { ErrorCodes } from '@heyputer/puter-js-common/src/PosixError.js' ;
22
+ import { find_repo_root , shorten_hash } from '../git-helpers.js' ;
23
+
24
+ export default {
25
+ name : 'commit' ,
26
+ args : {
27
+ allowPositionals : false ,
28
+ options : {
29
+ message : {
30
+ description : 'Specify the commit message' ,
31
+ type : 'string' ,
32
+ short : 'm' ,
33
+ } ,
34
+ author : {
35
+ description :
'Specify the commit author, as `A U Thor <[email protected] >`' ,
36
+ type : 'string' ,
37
+ } ,
38
+ } ,
39
+ } ,
40
+ execute : async ( ctx ) => {
41
+ const { io, fs, env, args } = ctx ;
42
+ const { stdout, stderr } = io ;
43
+ const { options, positionals } = args ;
44
+
45
+ if ( ! options . message ) {
46
+ // TODO: Support opening a temporary file in an editor,
47
+ // where the user can edit the commit message if it's not specified.
48
+ stderr ( 'You must specify a commit message with --message or -m' ) ;
49
+ return 1 ;
50
+ }
51
+
52
+ const { repository_dir, git_dir } = await find_repo_root ( fs , env . PWD ) ;
53
+
54
+ let user_name ;
55
+ let user_email ;
56
+
57
+ if ( options . author ) {
58
+ const author_regex = / ( .+ ?) \s + < ( .+ ) > / ;
59
+ const matches = options . author . match ( author_regex ) ;
60
+ if ( ! matches )
61
+ throw new Error ( 'Failed to parse author string' ) ;
62
+ user_name = matches [ 1 ] ;
63
+ user_email = matches [ 2 ] ;
64
+ } else {
65
+ user_name = await git . getConfig ( {
66
+ fs,
67
+ dir : repository_dir ,
68
+ gitdir : git_dir ,
69
+ path : 'user.name' ,
70
+ } ) ;
71
+ user_email = await git . getConfig ( {
72
+ fs,
73
+ dir : repository_dir ,
74
+ gitdir : git_dir ,
75
+ path : 'user.email' ,
76
+ } ) ;
77
+ }
78
+
79
+ if ( ! user_name || ! user_email ) {
80
+ throw new Error ( 'Missing author information. Either provide --author="A <[email protected] >" or set user.name and user.email in the git config' ) ;
81
+ }
82
+
83
+ const commit_hash = await git . commit ( {
84
+ fs,
85
+ dir : repository_dir ,
86
+ gitdir : git_dir ,
87
+ message : options . message ,
88
+ author : {
89
+ name : user_name ,
90
+ email : user_email ,
91
+ } ,
92
+ } ) ;
93
+
94
+ const branch = await git . currentBranch ( {
95
+ fs,
96
+ dir : repository_dir ,
97
+ gitdir : git_dir ,
98
+ } ) ;
99
+ const commit_title = options . message . split ( '\n' ) [ 0 ] ;
100
+ const short_hash = await shorten_hash ( commit_hash , { fs, repository_dir, git_dir} ) ;
101
+ let output = `[${ branch } ${ short_hash } ] ${ commit_title } \n` ;
102
+ // TODO: --amend prints out the date of the original commit here, as:
103
+ // ` Date: Fri May 17 15:45:47 2024 +0100`
104
+ // TODO: Print out file change count, insertion count, and deletion count
105
+ // (Seems if insertions and deletions are both 0, we should print both.
106
+ // Otherwise we just print nonzero ones.)
107
+ // TODO: Print out each file created or deleted. eg:
108
+ // create mode 100644 bar
109
+ // delete mode 100644 foo.txt
110
+ stdout ( output ) ;
111
+ }
112
+ }
0 commit comments