git-off

git off handles large files in git repos
git clone https://noulin.net/git/git-off.git
Log | Files | Refs | README

commit c440dc53aa3768e69bb7e55880cb93dc11dc9d13
parent cf2d41429646ebb12785bacea52f573bcc0aa0ed
Author: Remy Noulin (Spartatek) <remy.noulin@spartatek.se>
Date:   Wed, 23 Nov 2016 13:12:09 +0100

Expose ssh options

Add sshoptions and scpoptions commands

README.md         |   6 +++
src/git-off       | 136 ++++++++++++++++++++++++++++++++++++++++++++++--------
src/gitoff.coffee |  71 ++++++++++++++++++++++------
3 files changed, 178 insertions(+), 35 deletions(-)

Diffstat:
MREADME.md | 6++++++
Msrc/git-off | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/gitoff.coffee | 71++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
3 files changed, 178 insertions(+), 35 deletions(-)

diff --git a/README.md b/README.md @@ -115,6 +115,12 @@ git off pem [thisrepo] [pathToPrivateKey] set/show git off pem. off.pem is the private key for ssh and scp +git off sshoptions [thisrepo] [options] + set/show git off sshoptions. + +git off scpoptions [thisrepo] [options] + set/show git off scpoptions. + git off scp [thisrepo] [host] setup scp config host has format host:path diff --git a/src/git-off b/src/git-off @@ -80,8 +80,8 @@ externalHelpers = { 'gitCat': 'git cat-file -p', 'sha': 'git hash-object --no-filters', 'listAttr': 'git check-attr -a', - 'ssh': 'ssh -C -o StrictHostKeyChecking=no -o ConnectTimeout=3', - 'scp': 'scp -C -o StrictHostKeyChecking=no -o ConnectTimeout=3 -p' + 'ssh': 'ssh', + 'scp': 'scp' }; runtimeConfig = { @@ -92,6 +92,9 @@ runtimeConfig = { 'offIntegrity': '', 'offScp': '', 'offScpUser': '', + 'offPem': '', + 'offSshOptions': '', + 'offScpOptions': '', 'log': '' }; @@ -99,6 +102,9 @@ offDEFAULTS = { 'objectPath': '/.git/off/objects', 'mode': 'copy', 'integrity': 'disable', + 'pem': '', + 'sshOptions': '-C -o StrictHostKeyChecking=no -o ConnectTimeout=3', + 'scpOptions': '-C -o StrictHostKeyChecking=no -o ConnectTimeout=3 -p', 'store': '~/.git-off/offStore', 'log': '~/.git-off/log', '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 "$@"', @@ -219,21 +225,37 @@ offHelpers = { return runtimeConfig.offStore; }, 'offMode': function() { - var r; if (runtimeConfig.offMode === '') { - r = gitConfig.get('off.mode'); - runtimeConfig.offMode = expandHome(r); + runtimeConfig.offMode = gitConfig.get('off.mode'); } return runtimeConfig.offMode; }, 'offIntegrity': function() { - var r; if (runtimeConfig.offIntegrity === '') { - r = gitConfig.get('off.integrity'); - runtimeConfig.offIntegrity = expandHome(r); + runtimeConfig.offIntegrity = gitConfig.get('off.integrity'); } return runtimeConfig.offIntegrity; }, + 'offPem': function() { + var r; + if (runtimeConfig.offPem === '') { + r = gitConfig.get('off.pem'); + runtimeConfig.offPem = expandHome(r); + } + return runtimeConfig.offPem; + }, + 'offSshOptions': function() { + if (runtimeConfig.offSshOptions === '') { + runtimeConfig.offSshOptions = gitConfig.get('off.sshoptions'); + } + return runtimeConfig.offSshOptions; + }, + 'offScpOptions': function() { + if (runtimeConfig.offScpOptions === '') { + runtimeConfig.offScpOptions = gitConfig.get('off.scpoptions'); + } + return runtimeConfig.offScpOptions; + }, 'offScp': function() { if (runtimeConfig.offScp === '') { runtimeConfig.offScp = gitConfig.get('off.scphost'); @@ -293,25 +315,35 @@ offHelpers = { return [user + host, storePath, port]; }, 'mkdirStore': function(path) { - var h_l, sshCmd; + var h_l, pem, sshCmd; h_l = offHelpers.getSSHConfig(); sshCmd = '"mkdir -p ' + h_l[1] + '/' + path; sshCmd += '"'; + if (offHelpers.offPem() === '') { + pem = ''; + } else { + pem = '-i ' + offHelpers.offPem(); + } if (isNaN(h_l[2])) { - exec('ssh', [h_l[0], sshCmd], true); + exec('ssh', [offHelpers.offSshOptions(), pem, h_l[0], sshCmd], true); } else { - exec('ssh', ['-p ' + h_l[2], h_l[0], sshCmd], true); + exec('ssh', [offHelpers.offSshOptions(), pem, '-p ' + h_l[2], h_l[0], sshCmd], true); } }, 'rmAllStore': function(path) { - var h_l, sshCmd; + var h_l, pem, sshCmd; + if (offHelpers.offPem() === '') { + pem = ''; + } else { + pem = '-i ' + offHelpers.offPem(); + } h_l = offHelpers.getSSHConfig(); sshCmd = '"rm -rf ' + h_l[1] + '/' + path; sshCmd += '"'; if (isNaN(h_l[2])) { - exec('ssh', [h_l[0], sshCmd], true); + exec('ssh', [offHelpers.offSshOptions(), pem, h_l[0], sshCmd], true); } else { - exec('ssh', ['-p ' + h_l[2], h_l[0], sshCmd], true); + exec('ssh', [offHelpers.offSshOptions(), pem, '-p ' + h_l[2], h_l[0], sshCmd], true); } }, 'checkIntegrity': function(path) { @@ -349,27 +381,37 @@ offHelpers = { }; } else if (offHelpers.offMode() === 'scp') { transport['send'] = function(file) { - var f_l, h_l; + var f_l, h_l, pem; f_l = file.split('/'); offHelpers.mkdirStore(f_l[0] + '/' + f_l[1]); + if (offHelpers.offPem() === '') { + pem = ''; + } else { + pem = '-i ' + offHelpers.offPem(); + } h_l = offHelpers.getSSHConfig(); if (isNaN(h_l[2])) { - exec('scp', [offHelpers.objectPath() + '/' + file, h_l[0] + ':' + h_l[1] + '/' + file]); + exec('scp', [offHelpers.offScpOptions(), pem, offHelpers.objectPath() + '/' + file, h_l[0] + ':' + h_l[1] + '/' + file]); } else { - exec('scp', ['-P ' + h_l[2], offHelpers.objectPath() + '/' + file, h_l[0] + ':' + h_l[1] + '/' + file]); + exec('scp', [offHelpers.offScpOptions(), pem, '-P ' + h_l[2], offHelpers.objectPath() + '/' + file, h_l[0] + ':' + h_l[1] + '/' + file]); } }; transport['receive'] = function(file) { - var f_l, h_l, readStream; + var f_l, h_l, pem, readStream; f_l = file.split('/'); if (fs.existsSync(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]) === false) { mkdirParents(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]); } + if (offHelpers.offPem() === '') { + pem = ''; + } else { + pem = '-i ' + offHelpers.offPem(); + } h_l = offHelpers.getSSHConfig(); if (isNaN(h_l[2])) { - exec('scp', [h_l[0] + ':' + h_l[1] + '/' + file, offHelpers.objectPath() + '/' + file]); + exec('scp', [offHelpers.offScpOptions(), pem, h_l[0] + ':' + h_l[1] + '/' + file, offHelpers.objectPath() + '/' + file]); } else { - exec('scp', ['-P ' + h_l[2], h_l[0] + ':' + h_l[1] + '/' + file, offHelpers.objectPath() + '/' + file]); + exec('scp', [offHelpers.offScpOptions(), pem, '-P ' + h_l[2], h_l[0] + ':' + h_l[1] + '/' + file, offHelpers.objectPath() + '/' + file]); } if (offHelpers.checkIntegrity(offHelpers.objectPath() + '/' + file)) { readStream = fs.createReadStream(offHelpers.objectPath() + '/' + file); @@ -435,6 +477,15 @@ offCommands = { if (offHelpers.offIntegrity() === '' || setCfg !== gitConfig.set) { setCfg('off.integrity', offDEFAULTS.integrity); } + if (offHelpers.offPem() === '' || setCfg !== gitConfig.set) { + setCfg('off.pem', offDEFAULTS.pem); + } + if (offHelpers.offSshOptions() === '' || setCfg !== gitConfig.set) { + setCfg('off.sshoptions', offDEFAULTS.sshOptions); + } + if (offHelpers.offScpOptions() === '' || setCfg !== gitConfig.set) { + setCfg('off.scpoptions', offDEFAULTS.scpOptions); + } if (offHelpers.offStore() === '' || setCfg !== gitConfig.set) { setCfg('off.store', offDEFAULTS.store); } @@ -475,6 +526,36 @@ offCommands = { console.log('off.integrity '.blue.bold + offHelpers.offIntegrity()); } }, + 'pem': function(setCfg) { + var len, pem; + len = process.argv.length; + pem = process.argv[len - 1]; + if (pem !== 'pem' && pem !== 'thisrepo') { + setCfg('off.pem', pem); + } else { + console.log('off.pem '.blue.bold + offHelpers.offPem()); + } + }, + 'sshoptions': function(setCfg) { + var len, sshoptions; + len = process.argv.length; + sshoptions = process.argv[len - 1]; + if (sshoptions !== 'sshoptions' && sshoptions !== 'thisrepo') { + setCfg('off.sshoptions', sshoptions); + } else { + console.log('off.sshoptions '.blue.bold + offHelpers.offSshOptions()); + } + }, + 'scpoptions': function(setCfg) { + var len, scpoptions; + len = process.argv.length; + scpoptions = process.argv[len - 1]; + if (scpoptions !== 'scpoptions' && scpoptions !== 'thisrepo') { + setCfg('off.scpoptions', scpoptions); + } else { + console.log('off.scpoptions '.blue.bold + offHelpers.offScpOptions()); + } + }, 'scpUser': function(setCfg) { var len, scpUser; len = process.argv.length; @@ -624,6 +705,9 @@ offCommands = { 'env': function() { console.log('off.mode '.blue.bold + offHelpers.offMode()); console.log('off.integrity '.blue.bold + offHelpers.offIntegrity()); + console.log('off.pem '.blue.bold + offHelpers.offPem()); + console.log('off.sshoptions '.blue.bold + offHelpers.offSshOptions()); + console.log('off.scpoptions '.blue.bold + offHelpers.offScpOptions()); console.log('off.store '.blue.bold + offHelpers.offStore()); console.log('off.scphost '.blue.bold + offHelpers.offScp()); console.log('off.scpuser '.blue.bold + offHelpers.offScpUser()); @@ -660,6 +744,18 @@ if (process.argv[2] === 'integrity') { thisrepo(offCommands['integrity']); } +if (process.argv[2] === 'pem') { + thisrepo(offCommands['pem']); +} + +if (process.argv[2] === 'sshoptions') { + thisrepo(offCommands['sshoptions']); +} + +if (process.argv[2] === 'scpoptions') { + thisrepo(offCommands['scpoptions']); +} + if (process.argv[2] === 'scpuser') { thisrepo(offCommands['scpUser']); } diff --git a/src/gitoff.coffee b/src/gitoff.coffee @@ -4,7 +4,6 @@ # add multiple config like our git fat # add help # add rsync backend - change push and smudge -# add pem config # handle wrong config like getLog # add a command to copy stores # check parameters from CLI @@ -98,8 +97,8 @@ externalHelpers = 'gitCat': 'git cat-file -p' 'sha': 'git hash-object --no-filters' 'listAttr': 'git check-attr -a' - 'ssh': 'ssh -C -o StrictHostKeyChecking=no -o ConnectTimeout=3' - 'scp': 'scp -C -o StrictHostKeyChecking=no -o ConnectTimeout=3 -p' + 'ssh': 'ssh' + 'scp': 'scp' # config built by offHelpers # use offHelpers to access runtimeConfig @@ -112,6 +111,8 @@ runtimeConfig = 'offScp': '' 'offScpUser': '' 'offPem': '' + 'offSshOptions': '' + 'offScpOptions': '' 'log': '' # default configuration for first time install @@ -121,6 +122,8 @@ offDEFAULTS = 'mode': 'copy' 'integrity': 'disable' 'pem': '' + 'sshOptions': '-C -o StrictHostKeyChecking=no -o ConnectTimeout=3' + 'scpOptions': '-C -o StrictHostKeyChecking=no -o ConnectTimeout=3 -p' 'store': '~/.git-off/offStore' 'log': '~/.git-off/log' '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 "$@"' @@ -259,14 +262,12 @@ offHelpers = 'offMode': -> if runtimeConfig.offMode == '' - r = gitConfig.get 'off.mode' - runtimeConfig.offMode = expandHome r + runtimeConfig.offMode = gitConfig.get 'off.mode' runtimeConfig.offMode 'offIntegrity': -> if runtimeConfig.offIntegrity == '' - r = gitConfig.get 'off.integrity' - runtimeConfig.offIntegrity = expandHome r + runtimeConfig.offIntegrity = gitConfig.get 'off.integrity' runtimeConfig.offIntegrity 'offPem': -> @@ -275,6 +276,16 @@ offHelpers = runtimeConfig.offPem = expandHome r runtimeConfig.offPem + 'offSshOptions': -> + if runtimeConfig.offSshOptions == '' + runtimeConfig.offSshOptions = gitConfig.get 'off.sshoptions' + runtimeConfig.offSshOptions + + 'offScpOptions': -> + if runtimeConfig.offScpOptions == '' + runtimeConfig.offScpOptions = gitConfig.get 'off.scpoptions' + runtimeConfig.offScpOptions + 'offScp': -> if runtimeConfig.offScp == '' runtimeConfig.offScp = gitConfig.get 'off.scphost' @@ -346,9 +357,9 @@ offHelpers = # ignore error from mkdir for already existing store if isNaN h_l[2] - exec 'ssh', [pem, h_l[0], sshCmd], true + exec 'ssh', [offHelpers.offSshOptions(), pem, h_l[0], sshCmd], true else - exec 'ssh', [pem, '-p ' + h_l[2], h_l[0], sshCmd], true + exec 'ssh', [offHelpers.offSshOptions(), pem, '-p ' + h_l[2], h_l[0], sshCmd], true return 'rmAllStore': (path) -> @@ -367,9 +378,9 @@ offHelpers = sshCmd += '"' # ignore error from rm if isNaN h_l[2] - exec 'ssh', [pem, h_l[0], sshCmd], true + exec 'ssh', [offHelpers.offSshOptions(), pem, h_l[0], sshCmd], true else - exec 'ssh', [pem, '-p ' + h_l[2], h_l[0], sshCmd], true + exec 'ssh', [offHelpers.offSshOptions(), pem, '-p ' + h_l[2], h_l[0], sshCmd], true return 'checkIntegrity': (path) -> @@ -428,9 +439,9 @@ offHelpers = h_l = offHelpers.getSSHConfig() if isNaN h_l[2] - exec 'scp', [pem, offHelpers.objectPath() + '/' + file, h_l[0] + ':' + h_l[1] + '/' + file] + exec 'scp', [offHelpers.offScpOptions(), pem, offHelpers.objectPath() + '/' + file, h_l[0] + ':' + h_l[1] + '/' + file] else - exec 'scp', [pem, '-P ' + h_l[2], offHelpers.objectPath() + '/' + file, h_l[0] + ':' + h_l[1] + '/' + file] + exec 'scp', [offHelpers.offScpOptions(), pem, '-P ' + h_l[2], offHelpers.objectPath() + '/' + file, h_l[0] + ':' + h_l[1] + '/' + file] return transport['receive'] = (file) -> # create file directories in cache @@ -446,9 +457,9 @@ offHelpers = h_l = offHelpers.getSSHConfig() if isNaN h_l[2] - exec 'scp', [pem, h_l[0] + ':' + h_l[1] + '/' + file, offHelpers.objectPath() + '/' + file] + exec 'scp', [offHelpers.offScpOptions(), pem, h_l[0] + ':' + h_l[1] + '/' + file, offHelpers.objectPath() + '/' + file] else - exec 'scp', [pem, '-P ' + h_l[2], h_l[0] + ':' + h_l[1] + '/' + file, offHelpers.objectPath() + '/' + file] + exec 'scp', [offHelpers.offScpOptions(), pem, '-P ' + h_l[2], h_l[0] + ':' + h_l[1] + '/' + file, offHelpers.objectPath() + '/' + file] if offHelpers.checkIntegrity offHelpers.objectPath() + '/' + file readStream = fs.createReadStream(offHelpers.objectPath() + '/' + file) @@ -536,6 +547,10 @@ offCommands = setCfg('off.integrity', offDEFAULTS.integrity) if offHelpers.offPem() == '' or setCfg != gitConfig.set setCfg('off.pem', offDEFAULTS.pem) + if offHelpers.offSshOptions() == '' or setCfg != gitConfig.set + setCfg('off.sshoptions', offDEFAULTS.sshOptions) + if offHelpers.offScpOptions() == '' or setCfg != gitConfig.set + setCfg('off.scpoptions', offDEFAULTS.scpOptions) if offHelpers.offStore() == '' or setCfg != gitConfig.set setCfg('off.store',offDEFAULTS.store) @@ -584,6 +599,24 @@ offCommands = console.log 'off.pem '.blue.bold + offHelpers.offPem() return + 'sshoptions': (setCfg) -> + len = process.argv.length + sshoptions = process.argv[len-1] + if sshoptions != 'sshoptions' and sshoptions != 'thisrepo' + setCfg('off.sshoptions', sshoptions) + else + console.log 'off.sshoptions '.blue.bold + offHelpers.offSshOptions() + return + + 'scpoptions': (setCfg) -> + len = process.argv.length + scpoptions = process.argv[len-1] + if scpoptions != 'scpoptions' and scpoptions != 'thisrepo' + setCfg('off.scpoptions', scpoptions) + else + console.log 'off.scpoptions '.blue.bold + offHelpers.offScpOptions() + return + 'scpUser': (setCfg) -> len = process.argv.length scpUser = process.argv[len-1] @@ -804,6 +837,8 @@ offCommands = console.log 'off.mode '.blue.bold + offHelpers.offMode() console.log 'off.integrity '.blue.bold + offHelpers.offIntegrity() console.log 'off.pem '.blue.bold + offHelpers.offPem() + console.log 'off.sshoptions '.blue.bold + offHelpers.offSshOptions() + console.log 'off.scpoptions '.blue.bold + offHelpers.offScpOptions() console.log 'off.store '.blue.bold + offHelpers.offStore() console.log 'off.scphost '.blue.bold + offHelpers.offScp() console.log 'off.scpuser '.blue.bold + offHelpers.offScpUser() @@ -842,6 +877,12 @@ if process.argv[2] == 'integrity' if process.argv[2] == 'pem' thisrepo offCommands['pem'] +if process.argv[2] == 'sshoptions' + thisrepo offCommands['sshoptions'] + +if process.argv[2] == 'scpoptions' + thisrepo offCommands['scpoptions'] + if process.argv[2] == 'scpuser' thisrepo offCommands['scpUser']