💾 Archived View for gmi.noulin.net › gitRepositories › git-off › file › src › git-off.gmi captured on 2023-01-29 at 11:40:02. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
git-off (50220B)
1 #! /usr/bin/env node 2 /* 3 * CODE 4 * 5 * modules 6 * defaults 7 * helpers 8 * core 9 * main 10 * 11 * 12 * modules 13 * all dependencies 14 * 15 * defaults 16 * objInfo fields: for indexing cat-diff response in push command 17 * externalHelpers: shell commands to be used with the exec function 18 * runtimeConfig: config built by offHelpers 19 * offDEFAULTS: default configuration for first time install 20 * 21 * helpers 22 * expandHome: expands ~/ 23 * gitConfig: handles global git config 24 * offLog: appends log to git config off.log 25 * offLogRepo: log for commands run in git repo 26 * exec: runs an externalHelpers with parameters 27 * mkdirParents: recursive mkdir 28 * rmAll: delete recursively files and directories 29 * copy: copies files 30 * offHelpers: git-off helpers 31 * 32 * core 33 * transport: transport functions for git off store 34 * offCommands: command line functions 35 * 36 * main 37 * parse CLI arguments 38 */ 39 40 /* 41 * modules 42 */ 43 var COMMAND_MAP, StringDecoder, copy, exec, expandHome, externalHelpers, fs, fssync, gitConfig, mkdirParents, mkdirp, offCommands, offDEFAULTS, offHelpers, offLog, offLogRepo, oiNAME, oiOID, oiPERMISSIONS, oiPREVIOUSOID, oiPREVIOUSPERMISSIONS, path, readline, rimraf, rmAll, runtimeConfig, showCommandHelp, syncexec, thisrepo, transport, walkSync; 44 45 require('colors'); 46 47 fs = require('fs'); 48 49 path = require('path'); 50 51 fssync = require('fs-sync'); 52 53 syncexec = require('sync-exec'); 54 55 mkdirp = require('mkdirp'); 56 57 rimraf = require('rimraf'); 58 59 readline = require('readline'); 60 61 StringDecoder = require('string_decoder').StringDecoder; 62 63 64 /* 65 * defaults 66 */ 67 68 oiPREVIOUSPERMISSIONS = 0; 69 70 oiPERMISSIONS = 1; 71 72 oiPREVIOUSOID = 2; 73 74 oiOID = 3; 75 76 oiNAME = 4; 77 78 externalHelpers = { 79 'gitConfigGlobal': 'git config --global', 80 'gitConfig': 'git config', 81 'gitRepoRoot': 'git rev-parse --show-toplevel', 82 'gitList': 'git rev-list', 83 'gitListEmptyRemote': 'git rev-list --max-parents=0', 84 'gitDiff': 'git show --raw --format="" --no-abbrev', 85 'gitCat': 'git cat-file -p', 86 'sha': 'git hash-object --no-filters', 87 'listAttr': 'git check-attr -a', 88 'ssh': 'ssh', 89 'scp': 'scp', 90 'curl': 'curl', 91 'mv': 'mv', 92 'rsync': 'rsync' 93 }; 94 95 runtimeConfig = { 96 'currentRepoRoot': '', 97 'objectPath': '', 98 'offStore': '', 99 'offHttp': '', 100 'offMode': '', 101 'offIntegrity': '', 102 'offScp': '', 103 'offScpUser': '', 104 'offPem': '', 105 'offSshOptions': '', 106 'offScpOptions': '', 107 'offRsyncOptions': '', 108 'offCurlOptions': '', 109 'log': '', 110 'offConfigAlways': '', 111 's3Region': '', 112 's3Bucket': '', 113 'transform': '', 114 'transformTo': '', 115 'transformFrom': '' 116 }; 117 118 offDEFAULTS = { 119 'objectPath': '/.git/off/objects', 120 'mode': 'copy', 121 'integrity': 'disable', 122 'pem': 'offNoValue', 123 'scpHost': 'offNoValue', 124 'scpUser': '', 125 'sshOptions': '-C -o StrictHostKeyChecking=no -o ConnectTimeout=3', 126 'scpOptions': '-C -o StrictHostKeyChecking=no -o ConnectTimeout=3 -p', 127 'rsyncOptions': '-az -e \'ssh -i _i\'', 128 'store': '~/.git-off/offStore', 129 'http': 'offNoValue', 130 'curlOptions': '-o', 131 'log': '~/.git-off/log', 132 'configAlways': 'offNoValue', 133 's3Region': 'offNoValue', 134 's3Bucket': 'offNoValue', 135 'transform': 'disable', 136 'transformTo': 'pbzip2 -9 -c _1 > _2', 137 'transformFrom': 'pbzip2 -d -c _1 > _2', 138 'prePush': '#!/bin/sh\ncommand -v git-off >/dev/null 2>&1 || { echo >&2 "\\nThis repository is configured for Git off but \'git-off\' was not found on your path. If you no longer wish to use git off, remove this hook by deleting .git/hooks/pre-push.\\n"; exit 2; }\ngit off pre-push "$@"', 139 'offSignature': '### git-off v1 sha:', 140 'shaLength': 40 141 }; 142 143 144 /* 145 * helpers 146 */ 147 148 expandHome = function(p) { 149 if (p.slice(0, 2) === '~/') { 150 p = process.env.HOME + '/' + p.slice(2); 151 } 152 return p; 153 }; 154 155 gitConfig = { 156 'set': function(key, value) { 157 exec('gitConfig', ['--global', key, '"' + value + '"']); 158 }, 159 'setLocal': function(key, value) { 160 exec('gitConfig', [key, '"' + value + '"']); 161 }, 162 'setThisRepo': function(key, value) { 163 exec('gitConfig', ['--file ' + offHelpers.gitRepoRoot() + '/.git-off', key, '"' + value + '"']); 164 }, 165 'get': function(key) { 166 var r; 167 if (offHelpers.offConfigAlways() === 'GIT_OFF_CONFIG') { 168 r = ''; 169 if (process.env.GIT_OFF_CONFIG !== void 0 && fs.existsSync(process.env.GIT_OFF_CONFIG) === true) { 170 r = exec('gitConfig', ['--file ' + process.env.GIT_OFF_CONFIG, key]).stdout.trim(); 171 } 172 return r; 173 } 174 if (offHelpers.offConfigAlways() === 'repo') { 175 r = ''; 176 if (fs.existsSync(offHelpers.gitRepoRoot(true) + '/.git-off') === true) { 177 r = exec('gitConfig', ['--file ' + offHelpers.gitRepoRoot() + '/.git-off', key]).stdout.trim(); 178 } 179 return r; 180 } 181 if (offHelpers.offConfigAlways() === 'global') { 182 return exec('gitConfig', [key]).stdout.trim(); 183 } 184 if (process.env.GIT_OFF_CONFIG !== void 0 && fs.existsSync(process.env.GIT_OFF_CONFIG) === true) { 185 r = exec('gitConfig', ['--file ' + process.env.GIT_OFF_CONFIG, key]).stdout.trim(); 186 if (r !== '') { 187 return r; 188 } 189 } 190 if (fs.existsSync(offHelpers.gitRepoRoot(true) + '/.git-off') === true) { 191 r = exec('gitConfig', ['--file ' + offHelpers.gitRepoRoot() + '/.git-off', key]).stdout.trim(); 192 if (r !== '') { 193 return r; 194 } 195 } 196 return exec('gitConfig', [key]).stdout.trim(); 197 }, 198 'getSyncexec': function(key) { 199 return syncexec(externalHelpers.gitConfig + ' ' + key); 200 } 201 }; 202 203 mkdirParents = function(p) { 204 p = expandHome(p); 205 mkdirp.sync(p, function(err) { 206 console.error(err); 207 }); 208 }; 209 210 rmAll = function(p) { 211 p = expandHome(p); 212 rimraf.sync(p); 213 }; 214 215 offLog = function(s) { 216 var r; 217 if (runtimeConfig.log === '') { 218 r = gitConfig.getSyncexec('off.log'); 219 runtimeConfig.log = expandHome(r.stdout.trim()); 220 if (runtimeConfig.log === '') { 221 console.error('Missing off.log config. Run "git config --global off.log ~/.git-off/log".'.red.bold); 222 process.exit(1); 223 } 224 } 225 if (fs.existsSync(path.dirname(runtimeConfig.log)) === false) { 226 mkdirParents(path.dirname(runtimeConfig.log)); 227 } 228 fs.appendFileSync(runtimeConfig.log, s + '\n'); 229 }; 230 231 offLogRepo = function(s) { 232 offLog('REPO path: ' + offHelpers.gitRepoRoot() + ' ' + s); 233 }; 234 235 exec = function(cmdName, paramsArray, ignoreStderr) { 236 var r; 237 if (paramsArray == null) { 238 paramsArray = []; 239 } 240 if (ignoreStderr == null) { 241 ignoreStderr = false; 242 } 243 r = syncexec(externalHelpers[cmdName] + ' ' + paramsArray.join(' ')); 244 if (r.stderr !== '' && ignoreStderr === false) { 245 console.error(r.stderr.red.bold); 246 offLog(r.stderr.red.bold); 247 process.exit(1); 248 } 249 return r; 250 }; 251 252 copy = function(src, dst) { 253 fssync.copy(src, dst); 254 }; 255 256 walkSync = function(dir, filelist) { 257 var files; 258 if (filelist == null) { 259 filelist = []; 260 } 261 files = fs.readdirSync(dir); 262 files.forEach(function(file) { 263 if (fs.statSync(dir + '/' + file).isDirectory()) { 264 filelist = walkSync(dir + '/' + file, filelist); 265 } else { 266 filelist.push(dir + '/' + file); 267 } 268 }); 269 return filelist; 270 }; 271 272 offHelpers = { 273 'gitRepoRoot': function(ignoreStderr) { 274 var r; 275 if (ignoreStderr == null) { 276 ignoreStderr = false; 277 } 278 if (runtimeConfig.currentRepoRoot === '') { 279 r = exec('gitRepoRoot', [], ignoreStderr); 280 runtimeConfig.currentRepoRoot = r.stdout.trim(); 281 } 282 return runtimeConfig.currentRepoRoot; 283 }, 284 'objectPath': function() { 285 if (runtimeConfig.objectPath === '') { 286 runtimeConfig.objectPath = this.gitRepoRoot() + offDEFAULTS.objectPath; 287 } 288 return runtimeConfig.objectPath; 289 }, 290 'offStore': function() { 291 var r; 292 if (runtimeConfig.offStore === '') { 293 r = gitConfig.get('off.store'); 294 runtimeConfig.offStore = expandHome(r); 295 } 296 return runtimeConfig.offStore; 297 }, 298 'offHttp': function() { 299 if (runtimeConfig.offHttp === '') { 300 runtimeConfig.offHttp = gitConfig.get('off.http'); 301 } 302 return runtimeConfig.offHttp; 303 }, 304 'offCurlOptions': function() { 305 if (runtimeConfig.offCurlOptions === '') { 306 runtimeConfig.offCurlOptions = gitConfig.get('off.curloptions'); 307 } 308 return runtimeConfig.offCurlOptions; 309 }, 310 'offMode': function() { 311 if (runtimeConfig.offMode === '') { 312 runtimeConfig.offMode = gitConfig.get('off.mode'); 313 } 314 return runtimeConfig.offMode; 315 }, 316 'offIntegrity': function() { 317 if (runtimeConfig.offIntegrity === '') { 318 runtimeConfig.offIntegrity = gitConfig.get('off.integrity'); 319 } 320 return runtimeConfig.offIntegrity; 321 }, 322 'offPem': function() { 323 var r; 324 if (runtimeConfig.offPem === '') { 325 r = gitConfig.get('off.pem'); 326 runtimeConfig.offPem = expandHome(r); 327 } 328 return runtimeConfig.offPem; 329 }, 330 'offSshOptions': function() { 331 if (runtimeConfig.offSshOptions === '') { 332 runtimeConfig.offSshOptions = gitConfig.get('off.sshoptions'); 333 } 334 return runtimeConfig.offSshOptions; 335 }, 336 'offScpOptions': function() { 337 if (runtimeConfig.offScpOptions === '') { 338 runtimeConfig.offScpOptions = gitConfig.get('off.scpoptions'); 339 } 340 return runtimeConfig.offScpOptions; 341 }, 342 'offRsyncOptions': function() { 343 if (runtimeConfig.offRsyncOptions === '') { 344 runtimeConfig.offRsyncOptions = gitConfig.get('off.rsyncoptions'); 345 } 346 return runtimeConfig.offRsyncOptions; 347 }, 348 'offScp': function() { 349 if (runtimeConfig.offScp === '') { 350 runtimeConfig.offScp = gitConfig.get('off.scphost'); 351 } 352 return runtimeConfig.offScp; 353 }, 354 'offScpUser': function() { 355 if (runtimeConfig.offScpUser === '') { 356 runtimeConfig.offScpUser = gitConfig.get('off.scpuser'); 357 } 358 return runtimeConfig.offScpUser; 359 }, 360 'log': function() { 361 var r; 362 if (runtimeConfig.log === '') { 363 r = gitConfig.getSyncexec('off.log'); 364 runtimeConfig.log = expandHome(r.stdout.trim()); 365 } 366 return runtimeConfig.log; 367 }, 368 'getLog': function() { 369 offHelpers.log(); 370 if (runtimeConfig.log === '') { 371 console.error('Missing off.log config. Run "git config --global off.log ~/.git-off/log".'.red.bold); 372 process.exit(1); 373 } 374 return runtimeConfig.log; 375 }, 376 'offConfigAlways': function() { 377 var r; 378 if (runtimeConfig.offConfigAlways === '') { 379 r = gitConfig.getSyncexec('off.configAlways'); 380 runtimeConfig.offConfigAlways = r.stdout.trim(); 381 } 382 return runtimeConfig.offConfigAlways; 383 }, 384 's3Region': function() { 385 if (runtimeConfig.s3Region === '') { 386 runtimeConfig.s3Region = gitConfig.get('off.s3region'); 387 } 388 return runtimeConfig.s3Region; 389 }, 390 's3Bucket': function() { 391 if (runtimeConfig.s3Bucket === '') { 392 runtimeConfig.s3Bucket = gitConfig.get('off.s3bucket'); 393 } 394 return runtimeConfig.s3Bucket; 395 }, 396 'transform': function() { 397 if (runtimeConfig.transform === '') { 398 runtimeConfig.transform = gitConfig.get('off.transform'); 399 } 400 return runtimeConfig.transform; 401 }, 402 'transformTo': function() { 403 if (runtimeConfig.transformTo === '') { 404 runtimeConfig.transformTo = gitConfig.get('off.transformTo'); 405 } 406 return runtimeConfig.transformTo; 407 }, 408 'transformFrom': function() { 409 if (runtimeConfig.transformFrom === '') { 410 runtimeConfig.transformFrom = gitConfig.get('off.transformFrom'); 411 } 412 return runtimeConfig.transformFrom; 413 }, 414 'userAt': function() { 415 var user; 416 if (offHelpers.offScpUser() !== '') { 417 user = offHelpers.offScpUser() + '@'; 418 } else { 419 user = ''; 420 } 421 return user; 422 }, 423 'getSSHConfig': function() { 424 var h_l, host, port, portAndPath_l, storePath, user; 425 user = offHelpers.userAt(); 426 h_l = offHelpers.offScp().split(':'); 427 if (h_l[1] === void 0) { 428 port = NaN; 429 } else { 430 portAndPath_l = h_l[1].split('/'); 431 port = parseInt(portAndPath_l[0]); 432 } 433 if (isNaN(port)) { 434 host = h_l[0]; 435 storePath = h_l[1]; 436 } else { 437 host = h_l[0]; 438 storePath = '/' + portAndPath_l.slice(1).join('/'); 439 } 440 return [user + host, storePath, port]; 441 }, 442 'mkdirStore': function(p) { 443 var h_l, pem, sshCmd; 444 h_l = offHelpers.getSSHConfig(); 445 sshCmd = '"mkdir -p ' + h_l[1] + '/' + p; 446 sshCmd += '"'; 447 if (offHelpers.offPem() === '' || offHelpers.offPem() === 'offNoValue') { 448 pem = ''; 449 } else { 450 pem = '-i ' + offHelpers.offPem(); 451 } 452 if (isNaN(h_l[2])) { 453 exec('ssh', [offHelpers.offSshOptions(), pem, h_l[0], sshCmd], true); 454 } else { 455 exec('ssh', [offHelpers.offSshOptions(), pem, '-p ' + h_l[2], h_l[0], sshCmd], true); 456 } 457 }, 458 'rmAllStore': function(p) { 459 var h_l, pem, sshCmd; 460 if (offHelpers.offPem() === '' || offHelpers.offPem() === 'offNoValue') { 461 pem = ''; 462 } else { 463 pem = '-i ' + offHelpers.offPem(); 464 } 465 h_l = offHelpers.getSSHConfig(); 466 sshCmd = '"rm -rf ' + h_l[1] + '/' + p; 467 sshCmd += '"'; 468 if (isNaN(h_l[2])) { 469 exec('ssh', [offHelpers.offSshOptions(), pem, h_l[0], sshCmd], true); 470 } else { 471 exec('ssh', [offHelpers.offSshOptions(), pem, '-p ' + h_l[2], h_l[0], sshCmd], true); 472 } 473 }, 474 'copyTo': function() { 475 var f, files, i, j, len1, len2, tfiles; 476 tfiles = walkSync(offHelpers.objectPath()); 477 files = []; 478 for (i = 0, len1 = tfiles.length; i < len1; i++) { 479 f = tfiles[i]; 480 files.push(f.replace(offHelpers.objectPath() + '/', '')); 481 } 482 for (j = 0, len2 = files.length; j < len2; j++) { 483 f = files[j]; 484 transport.send(f); 485 } 486 }, 487 'checkIntegrity': function(p) { 488 var r, receivedSha, result; 489 result = true; 490 if (offHelpers.offIntegrity() === 'disable') { 491 return true; 492 } 493 r = exec('sha', [p]); 494 receivedSha = r.stdout.split(' ')[0].trim(); 495 if (path.basename(p) !== receivedSha) { 496 console.log('git-off: The file ' + p + ' differs from the one that was pushed.'); 497 result = false; 498 } 499 return result; 500 }, 501 'setTransport': function(mode) { 502 if (mode == null) { 503 mode = 'config'; 504 } 505 if (mode === 'config') { 506 mode = offHelpers.offMode(); 507 } 508 if (mode === 'copy') { 509 transport['send'] = function(file) { 510 var f_l; 511 f_l = file.split('/'); 512 if (fs.existsSync(offHelpers.offStore() + '/' + f_l[0] + '/' + f_l[1]) === false) { 513 mkdirParents(offHelpers.offStore() + '/' + f_l[0] + '/' + f_l[1]); 514 } 515 copy(offHelpers.objectPath() + '/' + file, offHelpers.offStore() + '/' + file); 516 fs.chmodSync(offHelpers.offStore() + '/' + file, '444'); 517 }; 518 transport['receive'] = function(file) { 519 var f_l, readStream; 520 if (offHelpers.transform() === 'enable' && offHelpers.transformFrom() !== '') { 521 f_l = file.split('/'); 522 if (fs.existsSync(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]) === false) { 523 mkdirParents(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]); 524 } 525 copy(offHelpers.offStore() + '/' + file, offHelpers.objectPath() + '/' + file); 526 transport['transformFrom'](file); 527 if (offHelpers.checkIntegrity(offHelpers.objectPath() + '/../tmp/' + file)) { 528 readStream = fs.createReadStream(offHelpers.objectPath() + '/../tmp/' + file); 529 readStream.pipe(process.stdout); 530 } 531 } else { 532 if (offHelpers.checkIntegrity(offHelpers.offStore() + '/' + file)) { 533 readStream = fs.createReadStream(offHelpers.offStore() + '/' + file); 534 readStream.pipe(process.stdout); 535 } 536 } 537 }; 538 } else if (mode === 'rsync') { 539 transport['send'] = function(file) { 540 var f_l, options; 541 f_l = file.split('/'); 542 offHelpers.mkdirStore(f_l[0] + '/' + f_l[1]); 543 options = offHelpers.offRsyncOptions(); 544 if (options.indexOf('_i') !== -1) { 545 if (offHelpers.offPem() !== '' && offHelpers.offPem() !== 'offNoValue') { 546 options = options.replace('_i', offHelpers.offPem()); 547 } 548 } 549 exec('rsync', [options, offHelpers.objectPath() + '/' + file, offHelpers.offScp() + '/' + file]); 550 }; 551 transport['receive'] = function(file) { 552 var f_l, options, readStream; 553 f_l = file.split('/'); 554 if (fs.existsSync(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]) === false) { 555 mkdirParents(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]); 556 } 557 options = offHelpers.offRsyncOptions(); 558 if (options.indexOf('_i') !== -1) { 559 if (offHelpers.offPem() !== '' && offHelpers.offPem() !== 'offNoValue') { 560 options = options.replace('_i', offHelpers.offPem()); 561 } 562 } 563 exec('rsync', [options, offHelpers.offScp() + '/' + file, offHelpers.objectPath() + '/' + file]); 564 if (offHelpers.transform() === 'enable' && offHelpers.transformFrom() !== '') { 565 transport['transformFrom'](file); 566 if (offHelpers.checkIntegrity(offHelpers.objectPath() + '/../tmp/' + file)) { 567 readStream = fs.createReadStream(offHelpers.objectPath() + '/../tmp/' + file); 568 readStream.pipe(process.stdout); 569 } 570 } else { 571 if (offHelpers.checkIntegrity(offHelpers.objectPath() + '/' + file)) { 572 readStream = fs.createReadStream(offHelpers.objectPath() + '/' + file); 573 readStream.pipe(process.stdout); 574 } 575 } 576 }; 577 } else if (mode === 'scp') { 578 transport['send'] = function(file) { 579 var f_l, h_l, pem; 580 f_l = file.split('/'); 581 offHelpers.mkdirStore(f_l[0] + '/' + f_l[1]); 582 if (offHelpers.offPem() === '' || offHelpers.offPem() === 'offNoValue') { 583 pem = ''; 584 } else { 585 pem = '-i ' + offHelpers.offPem(); 586 } 587 h_l = offHelpers.getSSHConfig(); 588 if (isNaN(h_l[2])) { 589 exec('scp', [offHelpers.offScpOptions(), pem, offHelpers.objectPath() + '/' + file, h_l[0] + ':' + h_l[1] + '/' + file]); 590 } else { 591 exec('scp', [offHelpers.offScpOptions(), pem, '-P ' + h_l[2], offHelpers.objectPath() + '/' + file, h_l[0] + ':' + h_l[1] + '/' + file]); 592 } 593 }; 594 transport['receive'] = function(file) { 595 var f_l, h_l, pem, readStream; 596 f_l = file.split('/'); 597 if (fs.existsSync(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]) === false) { 598 mkdirParents(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]); 599 } 600 if (offHelpers.offPem() === '' || offHelpers.offPem() === 'offNoValue') { 601 pem = ''; 602 } else { 603 pem = '-i ' + offHelpers.offPem(); 604 } 605 h_l = offHelpers.getSSHConfig(); 606 if (isNaN(h_l[2])) { 607 exec('scp', [offHelpers.offScpOptions(), pem, h_l[0] + ':' + h_l[1] + '/' + file, offHelpers.objectPath() + '/' + file]); 608 } else { 609 exec('scp', [offHelpers.offScpOptions(), pem, '-P ' + h_l[2], h_l[0] + ':' + h_l[1] + '/' + file, offHelpers.objectPath() + '/' + file]); 610 } 611 if (offHelpers.transform() === 'enable' && offHelpers.transformFrom() !== '') { 612 transport['transformFrom'](file); 613 if (offHelpers.checkIntegrity(offHelpers.objectPath() + '/../tmp/' + file)) { 614 readStream = fs.createReadStream(offHelpers.objectPath() + '/../tmp/' + file); 615 readStream.pipe(process.stdout); 616 } 617 } else { 618 if (offHelpers.checkIntegrity(offHelpers.objectPath() + '/' + file)) { 619 readStream = fs.createReadStream(offHelpers.objectPath() + '/' + file); 620 readStream.pipe(process.stdout); 621 } 622 } 623 }; 624 } else if (mode === 'http') { 625 transport['send'] = function(file) { 626 offLogRepo('Http mode is read-only: ' + file + ' is stored in cache only'); 627 }; 628 transport['receive'] = function(file) { 629 var f_l, readStream; 630 f_l = file.split('/'); 631 if (fs.existsSync(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]) === false) { 632 mkdirParents(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]); 633 } 634 exec('curl', [offHelpers.offCurlOptions(), offHelpers.objectPath() + '/' + file, offHelpers.offHttp() + '/' + file]); 635 if (offHelpers.transform() === 'enable' && offHelpers.transformFrom() !== '') { 636 transport['transformFrom'](file); 637 if (offHelpers.checkIntegrity(offHelpers.objectPath() + '/../tmp/' + file)) { 638 readStream = fs.createReadStream(offHelpers.objectPath() + '/../tmp/' + file); 639 readStream.pipe(process.stdout); 640 } 641 } else { 642 if (offHelpers.checkIntegrity(offHelpers.objectPath() + '/' + file)) { 643 readStream = fs.createReadStream(offHelpers.objectPath() + '/' + file); 644 readStream.pipe(process.stdout); 645 } 646 } 647 }; 648 } else if (mode === 's3') { 649 transport['send'] = function(file) { 650 var AWS, fileStream, s3, upParams; 651 AWS = require('aws-sdk'); 652 s3 = new AWS.S3({ 653 region: offHelpers.s3Region(), 654 signatureVersion: 'v4' 655 }); 656 upParams = { 657 Bucket: offHelpers.s3Bucket(), 658 Key: file, 659 Body: '' 660 }; 661 fileStream = fs.createReadStream(offHelpers.objectPath() + '/' + file); 662 upParams.Body = fileStream; 663 s3.upload(upParams, function(err, data) {}); 664 }; 665 transport['receive'] = function(file) { 666 var AWS, dlParams, f_l, fileStream, s3; 667 AWS = require('aws-sdk'); 668 s3 = new AWS.S3({ 669 region: offHelpers.s3Region(), 670 signatureVersion: 'v4' 671 }); 672 f_l = file.split('/'); 673 if (fs.existsSync(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]) === false) { 674 mkdirParents(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]); 675 } 676 dlParams = { 677 Bucket: offHelpers.s3Bucket(), 678 Key: file 679 }; 680 fileStream = fs.createWriteStream(offHelpers.objectPath() + '/' + file); 681 fileStream.on('finish', function() { 682 var readStream; 683 if (offHelpers.transform() === 'enable' && offHelpers.transformFrom() !== '') { 684 transport['transformFrom'](file); 685 if (offHelpers.checkIntegrity(offHelpers.objectPath() + '/../tmp/' + file)) { 686 readStream = fs.createReadStream(offHelpers.objectPath() + '/../tmp/' + file); 687 readStream.pipe(process.stdout); 688 } 689 } else { 690 if (offHelpers.checkIntegrity(offHelpers.objectPath() + '/' + file)) { 691 readStream = fs.createReadStream(offHelpers.objectPath() + '/' + file); 692 readStream.pipe(process.stdout); 693 } 694 } 695 }); 696 s3.getObject(dlParams, function(err, data) {}).on('httpData', function(chunk) { 697 fileStream.write(chunk); 698 }).on('httpDone', function() { 699 fileStream.end(); 700 }); 701 }; 702 } 703 }, 704 'getOffFilePath': function(offFile) { 705 return [offFile.slice(0, 2) + '/' + offFile.slice(2, 4) + '/' + offFile, offFile.slice(0, 2) + '/' + offFile.slice(2, 4)]; 706 } 707 }; 708 709 710 /* 711 * core 712 */ 713 714 transport = { 715 'send': function(src) {}, 716 'receive': function(src) {}, 717 'transformFrom': function(file) { 718 var cmd, offFile, offFilePath, r; 719 offFile = path.basename(file); 720 offFilePath = offHelpers.getOffFilePath(offFile); 721 if (fs.existsSync(offHelpers.objectPath() + '/../tmp/' + offFilePath[1]) === false) { 722 mkdirParents(offHelpers.objectPath() + '/../tmp/' + offFilePath[1]); 723 } 724 cmd = offHelpers.transformFrom(); 725 cmd = cmd.replace('_1', offHelpers.objectPath() + '/' + file).replace('_2', offHelpers.objectPath() + '/../tmp/' + file); 726 r = syncexec(cmd); 727 } 728 }; 729 730 offCommands = { 731 'localSetup': function() { 732 var hook; 733 mkdirParents(offHelpers.objectPath()); 734 hook = offHelpers.gitRepoRoot() + '/.git/hooks/pre-push'; 735 if (fs.existsSync(hook) === false) { 736 fs.writeFileSync(hook, offDEFAULTS.prePush); 737 fs.chmodSync(hook, '755'); 738 } 739 }, 740 'install': function(setCfg) { 741 if (setCfg == null) { 742 setCfg = gitConfig.set; 743 } 744 offCommands.localSetup(); 745 if (gitConfig.get('filter.off.clean') === '' || setCfg !== gitConfig.set) { 746 if (setCfg === gitConfig.setThisRepo) { 747 gitConfig.setLocal('filter.off.clean', 'git off clean %f'); 748 } else { 749 setCfg('filter.off.clean', 'git off clean %f'); 750 } 751 } 752 if (gitConfig.get('filter.off.smudge') === '' || setCfg !== gitConfig.set) { 753 if (setCfg === gitConfig.setThisRepo) { 754 gitConfig.setLocal('filter.off.smudge', 'git off smudge %f'); 755 } else { 756 setCfg('filter.off.smudge', 'git off smudge %f'); 757 } 758 } 759 if (offHelpers.log() === '' || setCfg !== gitConfig.set) { 760 gitConfig.set('off.log', offDEFAULTS.log); 761 } 762 if (offHelpers.offMode() === '' || setCfg !== gitConfig.set) { 763 setCfg('off.mode', offDEFAULTS.mode); 764 } 765 if (offHelpers.offIntegrity() === '' || setCfg !== gitConfig.set) { 766 setCfg('off.integrity', offDEFAULTS.integrity); 767 } 768 if (offHelpers.offPem() === '' || setCfg !== gitConfig.set) { 769 setCfg('off.pem', offDEFAULTS.pem); 770 } 771 if (offHelpers.offScp() === '' || setCfg !== gitConfig.set) { 772 setCfg('off.scphost', offDEFAULTS.scpHost); 773 } 774 if (offHelpers.offScpUser() === '' || setCfg !== gitConfig.set) { 775 setCfg('off.scpuser', offDEFAULTS.scpUser); 776 } 777 if (offHelpers.offSshOptions() === '' || setCfg !== gitConfig.set) { 778 setCfg('off.sshoptions', offDEFAULTS.sshOptions); 779 } 780 if (offHelpers.offScpOptions() === '' || setCfg !== gitConfig.set) { 781 setCfg('off.scpoptions', offDEFAULTS.scpOptions); 782 } 783 if (offHelpers.offRsyncOptions() === '' || setCfg !== gitConfig.set) { 784 setCfg('off.rsyncoptions', offDEFAULTS.rsyncOptions); 785 } 786 if (offHelpers.offStore() === '' || setCfg !== gitConfig.set) { 787 setCfg('off.store', offDEFAULTS.store); 788 } 789 if (offHelpers.offHttp() === '' || setCfg !== gitConfig.set) { 790 setCfg('off.http', offDEFAULTS.http); 791 } 792 if (offHelpers.offCurlOptions() === '' || setCfg !== gitConfig.set) { 793 setCfg('off.curloptions', offDEFAULTS.curlOptions); 794 } 795 if (offHelpers.offConfigAlways() === '' || setCfg !== gitConfig.set) { 796 setCfg('off.configAlways', offDEFAULTS.configAlways); 797 } 798 if (offHelpers.s3Region() === '' || setCfg !== gitConfig.set) { 799 setCfg('off.s3Region', offDEFAULTS.s3Region); 800 } 801 if (offHelpers.s3Bucket() === '' || setCfg !== gitConfig.set) { 802 setCfg('off.s3Bucket', offDEFAULTS.s3Bucket); 803 } 804 if (offHelpers.transform() === '' || setCfg !== gitConfig.set) { 805 setCfg('off.transform', offDEFAULTS.transform); 806 } 807 if (offHelpers.transformTo() === '' || setCfg !== gitConfig.set) { 808 setCfg('off.transformTo', offDEFAULTS.transformTo); 809 } 810 if (offHelpers.transformFrom() === '' || setCfg !== gitConfig.set) { 811 setCfg('off.transformFrom', offDEFAULTS.transformFrom); 812 } 813 if (runtimeConfig.offMode === 'copy') { 814 mkdirParents(runtimeConfig.offStore); 815 } 816 if (runtimeConfig.offMode === 'scp' || runtimeConfig.offMode === 'rsync') { 817 offHelpers.mkdirStore(''); 818 } 819 }, 820 'mode': function(setCfg) { 821 var len, mode; 822 len = process.argv.length; 823 mode = process.argv[len - 1]; 824 if (mode !== 'mode' && mode !== 'thisrepo') { 825 setCfg('off.mode', mode); 826 } else { 827 console.log('off.mode '.blue.bold + offHelpers.offMode()); 828 } 829 }, 830 'store': function(setCfg) { 831 var len, store; 832 len = process.argv.length; 833 store = process.argv[len - 1]; 834 if (store !== 'store' && store !== 'thisrepo') { 835 setCfg('off.store', store); 836 } else { 837 console.log('off.store '.blue.bold + offHelpers.offStore()); 838 } 839 }, 840 'scp': function(setCfg) { 841 var len, scpHost; 842 len = process.argv.length; 843 scpHost = process.argv[len - 1]; 844 if (scpHost !== 'scp' && scpHost !== 'thisrepo') { 845 setCfg('off.scphost', scpHost); 846 } else { 847 console.log('off.scp '.blue.bold + offHelpers.offScp()); 848 } 849 }, 850 'http': function(setCfg) { 851 var http, len; 852 len = process.argv.length; 853 http = process.argv[len - 1]; 854 if (http !== 'http' && http !== 'thisrepo') { 855 setCfg('off.http', http); 856 } else { 857 console.log('off.http '.blue.bold + offHelpers.offHttp()); 858 } 859 }, 860 'curl': function(setCfg) { 861 var curl, len; 862 len = process.argv.length; 863 curl = process.argv[len - 1]; 864 if (curl !== 'curl' && curl !== 'thisrepo') { 865 setCfg('off.curloptions', curl); 866 } else { 867 console.log('off.curloptions '.blue.bold + offHelpers.offCurlOptions()); 868 } 869 }, 870 'integrity': function(setCfg) { 871 var integrity, len; 872 len = process.argv.length; 873 integrity = process.argv[len - 1]; 874 if (integrity !== 'integrity' && integrity !== 'thisrepo') { 875 setCfg('off.integrity', integrity); 876 } else { 877 console.log('off.integrity '.blue.bold + offHelpers.offIntegrity()); 878 } 879 }, 880 'pem': function(setCfg) { 881 var len, pem; 882 len = process.argv.length; 883 pem = process.argv[len - 1]; 884 if (pem !== 'pem' && pem !== 'thisrepo') { 885 setCfg('off.pem', pem); 886 } else { 887 console.log('off.pem '.blue.bold + offHelpers.offPem()); 888 } 889 }, 890 'sshoptions': function(setCfg) { 891 var len, sshoptions; 892 len = process.argv.length; 893 sshoptions = process.argv[len - 1]; 894 if (sshoptions !== 'sshoptions' && sshoptions !== 'thisrepo') { 895 setCfg('off.sshoptions', sshoptions); 896 } else { 897 console.log('off.sshoptions '.blue.bold + offHelpers.offSshOptions()); 898 } 899 }, 900 'scpoptions': function(setCfg) { 901 var len, scpoptions; 902 len = process.argv.length; 903 scpoptions = process.argv[len - 1]; 904 if (scpoptions !== 'scpoptions' && scpoptions !== 'thisrepo') { 905 setCfg('off.scpoptions', scpoptions); 906 } else { 907 console.log('off.scpoptions '.blue.bold + offHelpers.offScpOptions()); 908 } 909 }, 910 'rsyncoptions': function(setCfg) { 911 var len, rsyncoptions; 912 len = process.argv.length; 913 rsyncoptions = process.argv[len - 1]; 914 if (rsyncoptions !== 'rsyncoptions' && rsyncoptions !== 'thisrepo') { 915 setCfg('off.rsyncoptions', rsyncoptions); 916 } else { 917 console.log('off.rsyncoptions '.blue.bold + offHelpers.offRsyncOptions()); 918 } 919 }, 920 'scpUser': function(setCfg) { 921 var len, scpUser; 922 len = process.argv.length; 923 scpUser = process.argv[len - 1]; 924 if (scpUser !== 'scpuser' && scpUser !== 'thisrepo') { 925 setCfg('off.scpuser', scpUser); 926 } else { 927 console.log('off.scpuser '.blue.bold + offHelpers.offScpUser()); 928 } 929 }, 930 'track': function() { 931 var i, l, len1, r, ref; 932 if (process.argv[3] !== void 0) { 933 offCommands.install(); 934 fs.appendFileSync(offHelpers.gitRepoRoot() + '/.gitattributes', process.argv[3] + ' filter=off -text\n'); 935 } else { 936 r = exec('listAttr', ['`cd ' + offHelpers.gitRepoRoot() + '; git ls-files`']); 937 ref = r.stdout.split('\n'); 938 for (i = 0, len1 = ref.length; i < len1; i++) { 939 l = ref[i]; 940 if (l.indexOf(': filter: off') !== -1) { 941 console.log(l); 942 } 943 } 944 } 945 }, 946 'configAlways': function() { 947 var configAlways, len; 948 len = process.argv.length; 949 configAlways = process.argv[len - 1]; 950 if (configAlways !== 'configAlways') { 951 gitConfig.set('off.configAlways', configAlways); 952 } else { 953 console.log('off.configAlways '.blue.bold + offHelpers.offConfigAlways()); 954 } 955 }, 956 's3region': function(setCfg) { 957 var len, region; 958 len = process.argv.length; 959 region = process.argv[len - 1]; 960 if (region !== 's3region' && region !== 'thisrepo') { 961 setCfg('off.s3region', region); 962 } else { 963 console.log('off.s3region '.blue.bold + offHelpers.s3Region()); 964 } 965 }, 966 's3bucket': function(setCfg) { 967 var bucket, len; 968 len = process.argv.length; 969 bucket = process.argv[len - 1]; 970 if (bucket !== 's3bucket' && bucket !== 'thisrepo') { 971 setCfg('off.s3bucket', bucket); 972 } else { 973 console.log('off.s3bucket '.blue.bold + offHelpers.s3Bucket()); 974 } 975 }, 976 'transform': function(setCfg) { 977 var len, setting; 978 len = process.argv.length; 979 setting = process.argv[len - 1]; 980 if (setting !== 'transform' && setting !== 'thisrepo') { 981 setCfg('off.transform', setting); 982 } else { 983 console.log('off.transform '.blue.bold + offHelpers.transform()); 984 } 985 }, 986 'transformTo': function(setCfg) { 987 var len, setting; 988 len = process.argv.length; 989 setting = process.argv[len - 1]; 990 if (setting !== 'transformTo' && setting !== 'thisrepo') { 991 setCfg('off.transformTo', setting); 992 } else { 993 console.log('off.transformTo '.blue.bold + offHelpers.transformTo()); 994 } 995 }, 996 'transformFrom': function(setCfg) { 997 var len, setting; 998 len = process.argv.length; 999 setting = process.argv[len - 1]; 1000 if (setting !== 'transformFrom' && setting !== 'thisrepo') { 1001 setCfg('off.transformFrom', setting); 1002 } else { 1003 console.log('off.transformFrom '.blue.bold + offHelpers.transformFrom()); 1004 } 1005 }, 1006 'clean': function() { 1007 var file, offFile, offFilePath, pipe, quotedFile, r, size, writeStream; 1008 offCommands.localSetup(); 1009 file = process.argv[3]; 1010 size = fs.statSync(file).size; 1011 quotedFile = '"' + file + '"'; 1012 r = exec('sha', [quotedFile]); 1013 offFile = r.stdout.split(' ')[0].trim(); 1014 offFilePath = offHelpers.getOffFilePath(offFile); 1015 if (fs.existsSync(offHelpers.objectPath() + '/' + offFilePath[1]) === false) { 1016 mkdirParents(offHelpers.objectPath() + '/' + offFilePath[1]); 1017 } 1018 offFilePath = offFilePath[0]; 1019 if (fs.existsSync(offHelpers.objectPath() + '/' + offFilePath) === false) { 1020 writeStream = fs.createWriteStream(offHelpers.objectPath() + '/' + offFilePath); 1021 pipe = process.stdin.pipe(writeStream); 1022 pipe.on('finish', function() { 1023 var cmd; 1024 fs.chmodSync(offHelpers.objectPath() + '/' + offFilePath, '444'); 1025 if (offHelpers.transform() === 'enable' && offHelpers.transformTo() !== '') { 1026 if (fs.existsSync(offHelpers.objectPath() + '/../tmp' === false)) { 1027 mkdirParents(offHelpers.objectPath() + '/../tmp'); 1028 } 1029 offFilePath = offHelpers.getOffFilePath(offFile); 1030 if (fs.existsSync(offHelpers.objectPath() + '/../tmp/' + offFilePath[1]) === false) { 1031 mkdirParents(offHelpers.objectPath() + '/../tmp/' + offFilePath[1]); 1032 } 1033 offFilePath = offFilePath[0]; 1034 exec('mv', [offHelpers.objectPath() + '/' + offFilePath, offHelpers.objectPath() + '/../tmp/' + offFilePath]); 1035 cmd = offHelpers.transformTo(); 1036 cmd = cmd.replace('_1', offHelpers.objectPath() + '/../tmp/' + offFilePath).replace('_2', offHelpers.objectPath() + '/' + offFilePath); 1037 r = syncexec(cmd); 1038 } 1039 }); 1040 } else { 1041 writeStream = fs.createWriteStream('/dev/null'); 1042 process.stdin.pipe(writeStream); 1043 } 1044 console.log(offDEFAULTS.offSignature + offFile + ' size:' + size); 1045 }, 1046 'prepush': function() { 1047 var rl; 1048 offHelpers.setTransport(); 1049 rl = readline.createInterface({ 1050 input: process.stdin, 1051 output: process.stdout, 1052 terminal: false 1053 }); 1054 rl.on('line', function(line) { 1055 offCommands.push(line); 1056 }); 1057 }, 1058 'push': function(line) { 1059 var commitListToPush, i, j, len, len1, len2, line_l, localRef, localSha, objInfo, objInfoList, offFile, offFilePath, offRef, oi, r, remoteName, remoteRef, remoteSha, sha, url; 1060 len = process.argv.length; 1061 remoteName = process.argv[len - 2]; 1062 url = process.argv[len - 1]; 1063 line_l = line.split(' '); 1064 localRef = line_l[0]; 1065 localSha = line_l[1]; 1066 remoteRef = line_l[2]; 1067 remoteSha = line_l[3]; 1068 r = 0; 1069 if (remoteSha === '0000000000000000000000000000000000000000') { 1070 r = exec('gitListEmptyRemote', [localSha]); 1071 } else { 1072 r = exec('gitList', [localSha, '^' + remoteSha]); 1073 } 1074 commitListToPush = r.stdout.split('\n'); 1075 commitListToPush = commitListToPush.slice(0, commitListToPush.length - 1); 1076 for (i = 0, len1 = commitListToPush.length; i < len1; i++) { 1077 sha = commitListToPush[i]; 1078 r = exec('gitDiff', [sha]); 1079 objInfoList = r.stdout.split('\n'); 1080 objInfoList = objInfoList.slice(1, objInfoList.length - 1); 1081 for (j = 0, len2 = objInfoList.length; j < len2; j++) { 1082 oi = objInfoList[j]; 1083 objInfo = oi.split(' '); 1084 if (objInfo[oiNAME].slice(0, 1) !== 'D') { 1085 r = exec('gitCat', [objInfo[oiOID]]); 1086 offRef = r.stdout.split('\n')[0]; 1087 if (offRef.indexOf(offDEFAULTS.offSignature) !== -1) { 1088 offFile = offRef.split(':')[1].split(' ')[0]; 1089 offFilePath = offHelpers.getOffFilePath(offFile)[0]; 1090 transport.send(offFilePath); 1091 } 1092 } 1093 } 1094 } 1095 }, 1096 'smudge': function() { 1097 var status; 1098 offHelpers.setTransport(); 1099 offCommands.localSetup(); 1100 status = 'header'; 1101 process.stdin.on('readable', function() { 1102 var cmd, data, decoder, header, offFile, offFilePath, r, readStream; 1103 if (status === 'header') { 1104 status = 'stream'; 1105 data = process.stdin.read(offDEFAULTS.offSignature.length + offDEFAULTS.shaLength); 1106 decoder = new StringDecoder('utf8'); 1107 if (data === null) { 1108 offLogRepo('smudge error: cant get data from stdin.'); 1109 process.exit(1); 1110 } 1111 header = decoder.write(data); 1112 if (header.slice(0, offDEFAULTS.offSignature.length) === offDEFAULTS.offSignature) { 1113 offFile = header.split(':')[1]; 1114 offFilePath = offHelpers.getOffFilePath(offFile)[0]; 1115 if (fs.existsSync(offHelpers.objectPath() + '/' + offFilePath) === true) { 1116 if (offHelpers.transform() === 'enable' && offHelpers.transformFrom() !== '') { 1117 if (fs.existsSync(offHelpers.objectPath() + '/../tmp' === false)) { 1118 mkdirParents(offHelpers.objectPath() + '/../tmp'); 1119 } 1120 offFilePath = offHelpers.getOffFilePath(offFile); 1121 if (fs.existsSync(offHelpers.objectPath() + '/../tmp/' + offFilePath[1]) === false) { 1122 mkdirParents(offHelpers.objectPath() + '/../tmp/' + offFilePath[1]); 1123 } 1124 offFilePath = offFilePath[0]; 1125 cmd = offHelpers.transformFrom(); 1126 cmd = cmd.replace('_1', offHelpers.objectPath() + '/' + offFilePath).replace('_2', offHelpers.objectPath() + '/../tmp/' + offFilePath); 1127 r = syncexec(cmd); 1128 readStream = fs.createReadStream(offHelpers.objectPath() + '/../tmp/' + offFilePath); 1129 } else { 1130 readStream = fs.createReadStream(offHelpers.objectPath() + '/' + offFilePath); 1131 } 1132 readStream.pipe(process.stdout); 1133 } else { 1134 transport.receive(offFilePath); 1135 } 1136 } else { 1137 process.stdout.write(data); 1138 process.stdin.pipe(process.stdout); 1139 } 1140 } 1141 }); 1142 }, 1143 'copyTo': function() { 1144 if (process.argv[3] === void 0) { 1145 console.log('Choose a mode where to copy the cache'.red.bold); 1146 return; 1147 } 1148 offHelpers.setTransport(process.argv[3]); 1149 offHelpers.copyTo(); 1150 }, 1151 'pushTo': function() { 1152 if (offHelpers.offMode() !== void 0) { 1153 offHelpers.setTransport(offHelpers.offMode()); 1154 offHelpers.copyTo(); 1155 } 1156 }, 1157 'clearAll': function() { 1158 offCommands.clearStore(); 1159 offCommands.clearCache(); 1160 rmAll(offHelpers.getLog()); 1161 }, 1162 'clearCache': function() { 1163 rmAll(offHelpers.gitRepoRoot() + '/.git/off'); 1164 }, 1165 'clearStore': function() { 1166 if (offHelpers.offMode() === 'copy') { 1167 rmAll(offHelpers.offStore()); 1168 } 1169 if (offHelpers.offMode() === 'scp' || offHelpers.offMode() === 'rsync') { 1170 offHelpers.rmAllStore(''); 1171 } 1172 }, 1173 'clearTmp': function() { 1174 rmAll(offHelpers.gitRepoRoot() + '/.git/off/tmp'); 1175 }, 1176 'defaults': function() { 1177 var i, k, len1, ref; 1178 ref = Object.keys(offDEFAULTS); 1179 for (i = 0, len1 = ref.length; i < len1; i++) { 1180 k = ref[i]; 1181 console.log(k.blue.bold + ' ' + offDEFAULTS[k]); 1182 } 1183 }, 1184 'env': function() { 1185 console.log('off.mode '.blue.bold + offHelpers.offMode()); 1186 console.log('off.integrity '.blue.bold + offHelpers.offIntegrity()); 1187 console.log('off.pem '.blue.bold + offHelpers.offPem()); 1188 console.log('off.sshoptions '.blue.bold + offHelpers.offSshOptions()); 1189 console.log('off.scpoptions '.blue.bold + offHelpers.offScpOptions()); 1190 console.log('off.rsyncoptions '.blue.bold + offHelpers.offRsyncOptions()); 1191 console.log('off.store '.blue.bold + offHelpers.offStore()); 1192 console.log('off.http '.blue.bold + offHelpers.offHttp()); 1193 console.log('off.curloptions '.blue.bold + offHelpers.offCurlOptions()); 1194 console.log('off.scphost '.blue.bold + offHelpers.offScp()); 1195 console.log('off.scpuser '.blue.bold + offHelpers.offScpUser()); 1196 console.log('off.log '.blue.bold + offHelpers.getLog()); 1197 console.log('off.configAlways '.blue.bold + offHelpers.offConfigAlways()); 1198 console.log('off.s3region '.blue.bold + offHelpers.s3Region()); 1199 console.log('off.s3bucket '.blue.bold + offHelpers.s3Bucket()); 1200 console.log('off.transform '.blue.bold + offHelpers.transform()); 1201 console.log('off.transformTo '.blue.bold + offHelpers.transformTo()); 1202 console.log('off.transformFrom '.blue.bold + offHelpers.transformFrom()); 1203 }, 1204 'help': function() { 1205 var c, i, len1, ref; 1206 console.log('git-off help\n'.green.bold); 1207 if (process.argv[3] === void 0) { 1208 console.log('# Quick Start'.green.bold); 1209 console.log('Setup:'); 1210 console.log("git off track '*.bin'"); 1211 console.log('git add .'); 1212 console.log('git commit'); 1213 console.log('git push'); 1214 console.log('git checkout master'); 1215 console.log('\n# Other'.green.bold); 1216 console.log('git off install'); 1217 console.log('git off mode scp'); 1218 console.log('git off scp localhost:/tmp/offStore'); 1219 console.log('git off scpuser username'); 1220 console.log('git off cc'); 1221 console.log('git off ca'); 1222 console.log('git off env'); 1223 console.log('git off defaults\n'); 1224 ref = Object.keys(COMMAND_MAP); 1225 for (i = 0, len1 = ref.length; i < len1; i++) { 1226 c = ref[i]; 1227 showCommandHelp(c); 1228 } 1229 console.log('\nGo to https://noulin.net/git-off/file/README.md.html for more information'.green.bold); 1230 } else { 1231 if (COMMAND_MAP[process.argv[3]] === void 0) { 1232 console.log(COMMAND_MAP.help.h.green); 1233 } else { 1234 showCommandHelp(process.argv[3]); 1235 } 1236 } 1237 } 1238 }; 1239 1240 1241 /* 1242 * main 1243 */ 1244 1245 thisrepo = function(cmd) { 1246 if (process.argv[3] !== 'thisrepo') { 1247 cmd(gitConfig['set']); 1248 } else { 1249 cmd(gitConfig['setThisRepo']); 1250 } 1251 }; 1252 1253 showCommandHelp = function(cmd) { 1254 var l_l; 1255 l_l = COMMAND_MAP[cmd].h.split('\n'); 1256 console.log(l_l[0]); 1257 l_l = l_l.slice(1); 1258 console.log(l_l.join('\n').green); 1259 }; 1260 1261 COMMAND_MAP = { 1262 'install': { 1263 f: function() { 1264 thisrepo(offCommands['install']); 1265 }, 1266 h: 'git off install [thisrepo]\n setup git config (default global)\n thisrepo sets up config in current repo' 1267 }, 1268 'mode': { 1269 f: function() { 1270 thisrepo(offCommands['mode']); 1271 }, 1272 h: 'git off mode [thisrepo] [copy|rsync|scp|http|s3]\n set/show git off mode' 1273 }, 1274 'store': { 1275 f: function() { 1276 thisrepo(offCommands['store']); 1277 }, 1278 h: 'git off store [thisrepo] [path]\n set/show git off store path for copy mode' 1279 }, 1280 'scp': { 1281 f: function() { 1282 thisrepo(offCommands['scp']); 1283 }, 1284 h: 'git off scp [thisrepo] [host]\n setup scp config\n host has format host:path, user@host:path, user@host:port/path\n Example: localhost:/tmp/offStore' 1285 }, 1286 'http': { 1287 f: function() { 1288 thisrepo(offCommands['http']); 1289 }, 1290 h: 'git off http [thisrepo] [host]\n setup http config\n host has format http://host/path\n Example: http://localhost/offStore' 1291 }, 1292 'curl': { 1293 f: function() { 1294 thisrepo(offCommands['curl']); 1295 }, 1296 h: 'git off curl [thisrepo] [options]\n setup curl config' 1297 }, 1298 'integrity': { 1299 f: function() { 1300 thisrepo(offCommands['integrity']); 1301 }, 1302 h: 'git off integrity [thisrepo] [enable|disable]\n set/show git off integrity.\n when enabled, the SHA of the file received from the store is\n checked again the SHA of the original file' 1303 }, 1304 'pem': { 1305 f: function() { 1306 thisrepo(offCommands['pem']); 1307 }, 1308 h: "git off pem [thisrepo] [pathToPrivateKey]\n set/show git off pem.\n off.pem is the private key for ssh, rsync and scp\n set 'offNoValue' to set an empty value (useful when there are multiple configs)" 1309 }, 1310 'sshoptions': { 1311 f: function() { 1312 thisrepo(offCommands['sshoptions']); 1313 }, 1314 h: 'git off sshoptions [thisrepo] [options]\n set/show git off sshoptions' 1315 }, 1316 'scpoptions': { 1317 f: function() { 1318 thisrepo(offCommands['scpoptions']); 1319 }, 1320 h: 'git off scpoptions [thisrepo] [options]\n set/show git off scpoptions' 1321 }, 1322 'rsyncoptions': { 1323 f: function() { 1324 thisrepo(offCommands['rsyncoptions']); 1325 }, 1326 h: 'git off rsyncoptions [thisrepo] [options]\n set/show git off rsyncoptions' 1327 }, 1328 'scpuser': { 1329 f: function() { 1330 thisrepo(offCommands['scpUser']); 1331 }, 1332 h: 'git off scpuser [thisrepo] [username]\n setup scp username config' 1333 }, 1334 'track': { 1335 f: function() { 1336 offCommands.track(); 1337 }, 1338 h: "git off track\n setup gitattribute filters\n example: git off track '*.bin'\n without parameter, list git off attributes\n calls git off install" 1339 }, 1340 'configAlways': { 1341 f: function() { 1342 offCommands.configAlways(); 1343 }, 1344 h: "git off configAlways [''|GIT_OFF_CONFIG|repo|global]\n '' disable configAlways\n GIT_OFF_CONFIG load all configurations from $GIT_OFF_CONFIG\n repo load all configurations from current git repo\n global load all configurations from global git config\n set 'offNoValue' to set an empty value" 1345 }, 1346 's3region': { 1347 f: function() { 1348 thisrepo(offCommands['s3region']); 1349 }, 1350 h: 'git off s3region [thisrepo] [region]\n setup amazon s3 region for the bucket' 1351 }, 1352 's3bucket': { 1353 f: function() { 1354 thisrepo(offCommands['s3bucket']); 1355 }, 1356 h: 'git off s3bucket [thisrepo] [bucket]\n setup amazon s3 bucket' 1357 }, 1358 'transform': { 1359 f: function() { 1360 thisrepo(offCommands['transform']); 1361 }, 1362 h: 'git off transform [thisrepo] [enable|disable]\n enable transform in clean and smudge filters' 1363 }, 1364 'transformTo': { 1365 f: function() { 1366 thisrepo(offCommands['transformTo']); 1367 }, 1368 h: "git off transformTo [thisrepo] ['cmd _1 _2']\n setup transform command for clear filter\n When the command is empty the regular transport is performed" 1369 }, 1370 'transformFrom': { 1371 f: function() { 1372 thisrepo(offCommands['transformFrom']); 1373 }, 1374 h: "git off transformFrom [thisrepo] ['cmd _1 _2']\n setup transform command for smudge filter\n When the command is empty the regular transport is performed" 1375 }, 1376 'clean': { 1377 f: function() { 1378 offCommands.clean(); 1379 }, 1380 h: 'git off clean\n internal filter\n dont use directly' 1381 }, 1382 'pre-push': { 1383 f: function() { 1384 offCommands.prepush(); 1385 }, 1386 h: 'git off pre-push\n internal filter\n dont use directly' 1387 }, 1388 'smudge': { 1389 f: function() { 1390 offCommands.smudge(); 1391 }, 1392 h: 'git off smudge\n internal filter\n dont use directly' 1393 }, 1394 'copyTo': { 1395 f: function() { 1396 offCommands.copyTo(); 1397 }, 1398 h: 'git off copyTo [copy|rsync|scp|s3]\n copy cache to store for specified mode' 1399 }, 1400 'push': { 1401 f: function() { 1402 offCommands.pushTo(); 1403 }, 1404 h: 'git off push\n copy cache to store for selected mode' 1405 }, 1406 'clearAll': { 1407 f: function() { 1408 offCommands.clearAll(); 1409 }, 1410 h: 'git off clearAll\n delete store, cache and log' 1411 }, 1412 'ca': { 1413 f: function() { 1414 offCommands.clearAll(); 1415 }, 1416 h: 'git off ca\n delete store, cache and log' 1417 }, 1418 'clearCache': { 1419 f: function() { 1420 offCommands.clearCache(); 1421 }, 1422 h: 'git off clearCache\n delete cache in current git' 1423 }, 1424 'cc': { 1425 f: function() { 1426 offCommands.clearCache(); 1427 }, 1428 h: 'git off cc\n delete cache in current git' 1429 }, 1430 'clearStore': { 1431 f: function() { 1432 offCommands.clearStore(); 1433 }, 1434 h: 'git off clearStore\n delete store' 1435 }, 1436 'cs': { 1437 f: function() { 1438 offCommands.clearStore(); 1439 }, 1440 h: 'git off ct\n delete store' 1441 }, 1442 'clearTmp': { 1443 f: function() { 1444 offCommands.clearTmp(); 1445 }, 1446 h: 'git off clearTmp\n delete tmp in git off cache\n Useful when transform is enabled' 1447 }, 1448 'ct': { 1449 f: function() { 1450 offCommands.clearTmp(); 1451 }, 1452 h: 'git off cs\n delete tmp in git off cache\n Useful when transform is enabled' 1453 }, 1454 'defaults': { 1455 f: function() { 1456 offCommands.defaults(); 1457 }, 1458 h: 'git off defaults\n shows first time config' 1459 }, 1460 'env': { 1461 f: function() { 1462 offCommands.env(); 1463 }, 1464 h: 'git off env\n shows config' 1465 }, 1466 'help': { 1467 f: function() { 1468 offCommands.help(); 1469 }, 1470 h: 'git off help [cmd]\n git off help. Run git off help command to get help for a specific command.' 1471 } 1472 }; 1473 1474 if (process.argv[2] === void 0) { 1475 COMMAND_MAP.help.f(); 1476 } else { 1477 if (COMMAND_MAP[process.argv[2]] === void 0) { 1478 COMMAND_MAP['help'].f(); 1479 } else { 1480 COMMAND_MAP[process.argv[2]].f(); 1481 } 1482 } 1483 1484 1485 /* 1486 * exports for unit tests 1487 * export everything 1488 */ 1489 1490 module.exports = { 1491 runtimeConfig: runtimeConfig, 1492 offDEFAULTS: offDEFAULTS, 1493 expandHome: expandHome, 1494 gitConfig: gitConfig, 1495 offLog: offLog, 1496 offLogRepo: offLogRepo, 1497 exec: exec, 1498 mkdirParents: mkdirParents, 1499 rmAll: rmAll, 1500 copy: copy, 1501 walkSync: walkSync, 1502 offHelpers: offHelpers, 1503 transport: transport, 1504 offCommands: offCommands, 1505 thisrepo: thisrepo, 1506 showCommandHelp: showCommandHelp, 1507 COMMAND_MAP: COMMAND_MAP 1508 };