@@ -3,8 +3,7 @@ const fp = require('fs').promises
3
3
const path = require ( 'path' )
4
4
const url = require ( 'url' )
5
5
const EventEmitter = require ( 'events' ) . EventEmitter
6
- const { E, indexPack, plugins, readObject, verify } = require ( 'isomorphic-git' )
7
- const { serveInfoRefs, serveReceivePack, parseReceivePackRequest } = require ( 'isomorphic-git/dist/for-node/isomorphic-git/internal-apis.js' )
6
+ const { E, indexPack, plugins, readObject, verify, serveInfoRefs, serveReceivePack, parseReceivePackRequest } = require ( 'isomorphic-git' )
8
7
const { pgp } = require ( '@isomorphic-git/pgp-plugin' )
9
8
10
9
let ee = new EventEmitter ( )
@@ -16,6 +15,7 @@ const chalk = require('chalk')
16
15
const is = require ( './identify-request.js' )
17
16
const parse = require ( './parse-request.js' )
18
17
const { lookup, demote } = require ( './lookup.js' )
18
+ const { sandbox } = require ( './sandbox.js' )
19
19
20
20
function pad ( str ) {
21
21
return ( str + ' ' ) . slice ( 0 , 7 )
@@ -27,6 +27,8 @@ function abbr (oid) {
27
27
28
28
const sleep = ms => new Promise ( cb => setTimeout ( cb , ms ) )
29
29
30
+ const tick = ( ) => new Promise ( cb => process . nextTick ( cb ) )
31
+
30
32
function log ( req , res ) {
31
33
const color = res . statusCode > 399 ? chalk . red : chalk . green
32
34
console . log ( color ( `[git-server] ${ res . statusCode } ${ pad ( req . method ) } ${ req . url } ` ) )
@@ -86,6 +88,8 @@ function factory (config) {
86
88
filepath = `pack-${ last20 } .pack`
87
89
await fp . rename ( path . join ( dir , oldfilepath ) , path . join ( dir , filepath ) )
88
90
}
91
+ const core = gitdir + '-' + String ( Math . random ( ) ) . slice ( 2 , 8 )
92
+ console . log ( 'core' , core )
89
93
gitdir = path . join ( __dirname , gitdir )
90
94
91
95
// send HTTP response headers
@@ -95,19 +99,18 @@ function factory (config) {
95
99
// index packfile
96
100
res . write ( await serveReceivePack ( { type : 'print' , message : 'Indexing packfile...' } ) )
97
101
console . log ( 'Indexing packfile...' )
98
- await sleep ( 1 )
102
+ await tick ( )
99
103
let currentPhase = null
100
104
const listener = async ( { phase, loaded, total, lengthComputable } ) => {
101
105
let np = phase !== currentPhase ? '\n' : '\r'
102
106
currentPhase = phase
103
107
res . write ( await serveReceivePack ( { type : 'print' , message : `${ np } ${ phase } ${ loaded } /${ total } ` } ) )
104
- res . flush ( )
105
108
}
106
109
let oids
107
110
try {
108
111
ee . on ( `${ last20 } :progress` , listener )
109
112
oids = await indexPack ( { fs, gitdir, dir, filepath, emitterPrefix : `${ last20 } :` } )
110
- await sleep ( 1 )
113
+ await tick ( )
111
114
res . write ( await serveReceivePack ( { type : 'print' , message : '\nIndexing completed' } ) )
112
115
res . write ( await serveReceivePack ( { type : 'unpack' , unpack : 'ok' } ) )
113
116
} catch ( e ) {
@@ -121,59 +124,18 @@ function factory (config) {
121
124
} finally {
122
125
ee . removeListener ( `${ last20 } :progress` , listener )
123
126
}
124
- await sleep ( 1 )
127
+ await tick ( )
125
128
126
129
// Move packfile and index into repo
127
130
await fp . rename ( path . join ( dir , filepath ) , path . join ( gitdir , 'objects' , 'pack' , filepath ) )
128
131
await fp . rename ( path . join ( dir , filepath . replace ( / \. p a c k $ / , '.idx' ) ) , path . join ( gitdir , 'objects' , 'pack' , filepath . replace ( / \. p a c k $ / , '.idx' ) ) )
129
132
await fp . rmdir ( path . join ( dir ) )
130
133
131
- // Verify objects (ideally we'd do this _before_ moving it into the repo... but I think we'd need a custom 'fs' implementation with overlays)
132
- res . write ( await serveReceivePack ( { type : 'print' , message : '\nVerifying objects...\n' } ) )
133
- let i = 0
134
-
135
- for ( const oid of oids ) {
136
- i ++
137
- res . write ( await serveReceivePack ( { type : 'print' , message : `\rVerifying object ${ i } /${ oids . length } ` } ) )
138
- const { type, object } = await readObject ( { gitdir, oid } )
139
- if ( type === 'commit' || type === 'tag' ) {
140
- const email = type === 'commit' ? object . author . email : object . tagger . email
141
- res . write ( await serveReceivePack ( { type : 'print' , message : `\nVerifying ${ type } ${ abbr ( oid ) } by ${ email } : ` } ) )
142
- let keys
143
- try {
144
- keys = await lookup ( email )
145
- } catch ( e ) {
146
- res . write ( await serveReceivePack ( { type : 'print' , message : `no keys found 👎\n` } ) )
147
- throw e
148
- }
149
- if ( keys . length === 0 ) {
150
- res . write ( await serveReceivePack ( { type : 'print' , message : `no keys found 👎\n` } ) )
151
- throw new Error ( `\nSignature verification failed for ${ type } ${ abbr ( oid ) } . No PGP keys could be found for ${ email } .\n` )
152
- }
153
- let ok = false
154
- for ( const key of keys ) {
155
- const result = await verify ( { gitdir, ref : oid , publicKeys : key } )
156
- if ( result === false ) {
157
- demote ( email , key )
158
- } else {
159
- res . write ( await serveReceivePack ( { type : 'print' , message : `signed with ${ result [ 0 ] } 👍\n` } ) )
160
- ok = true
161
- break
162
- }
163
- }
164
- if ( ! ok ) {
165
- res . write ( await serveReceivePack ( { type : 'print' , message : `no keys matched 👎\n` } ) )
166
- throw new Error ( `\nSignature verification failed for ${ type } ${ abbr ( oid ) } . It was not signed with a key publicly associated with the email address "${ email } ".
167
-
168
- Learn how you can associate your GPG key with your email account using GitHub here:
169
- https://help.github.com/en/github/authenticating-to-github/adding-a-new-gpg-key-to-your-github-account
170
- ` )
171
- }
172
- }
173
- // await sleep(1)
174
- }
175
-
176
- res . write ( await serveReceivePack ( { type : 'print' , message : `\nVerification complete` } ) )
134
+ // Run pre-receive-hook
135
+ res . write ( await serveReceivePack ( { type : 'print' , message : '\nRunning pre-receive-hook\n' } ) )
136
+ await tick ( )
137
+ const script = fs . readFileSync ( './pre-receive-hook.js' , 'utf8' )
138
+ await sandbox ( { core, dir, gitdir, res, oids, script } )
177
139
178
140
// refs
179
141
for ( const update of updates ) {
@@ -185,14 +147,6 @@ https://help.github.com/en/github/authenticating-to-github/adding-a-new-gpg-key-
185
147
} catch ( e ) {
186
148
if ( e . message === 'Client is done' ) {
187
149
res . statusCode = 200
188
- } else if ( e . code && e . code === E . NoSignatureError ) {
189
- res . write ( await serveReceivePack ( { type : 'print' , message : `no signature 👎\n` } ) )
190
- res . write ( await serveReceivePack ( { type : 'error' , message : e . message + `
191
-
192
- This server's policy is to only accept GPG-signed commits.
193
- Learn how you can create a GPG key and configure git to sign commits here:
194
- https://help.github.com/en/github/authenticating-to-github/managing-commit-signature-verification
195
- ` } ) )
196
150
} else {
197
151
res . write ( await serveReceivePack ( { type : 'error' , message : e . message } ) )
198
152
}
0 commit comments