commit 8b13cb1840d788ac8c4798825d1a32c946e744ac
parent d9bdc4ac0462b69b536ef2b9434538ab75b6c519
Author: Remy Noulin (Spartatek) <remy.noulin@spartatek.se>
Date: Thu, 24 Nov 2016 19:15:48 +0100
add http transport and store command
- git off mode [thisrepo] http to use http transport
- git off store to set local store path
- git off http to set store url
- git off curl to set curl options
README.md | 18 +++-
package.json | 2 +-
src/git-off | 260 +++++++++++++++++++++++++++++++++++++++++++++++-------
src/gitoff.coffee | 94 +++++++++++++++++++-
4 files changed, 340 insertions(+), 34 deletions(-)
Diffstat:
| M | README.md | | | 18 | ++++++++++++++++-- |
| M | package.json | | | 2 | +- |
| M | src/git-off | | | 260 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- |
| M | src/gitoff.coffee | | | 94 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
4 files changed, 340 insertions(+), 34 deletions(-)
diff --git a/README.md b/README.md
@@ -4,6 +4,12 @@ This is a prototype inspired by [git lfs](https://github.com/git-lfs/git-lfs) an
By default the files are stored in the home directory.
+Supported transports are:
+
+- copy - store locally
+- ssh/scp
+- http
+
# Install
```
@@ -111,12 +117,19 @@ host localhost
git off install [thisrepo]
setup git config (default global)
thisrepo sets up config in current repo
-git off mode [thisrepo] [copy|scp]
+git off mode [thisrepo] [copy|scp|http]
set/show git off mode
+git off store [thisrepo] [path]
+ set/show git off store path for copy mode
git off scp [thisrepo] [host]
setup scp config
host has format host:path, user@host:path, user@host:port/path
Example: localhost:/tmp/offStore
+git off http [thisrepo] [host]
+ setup http config
+ host has format http://host/path
+git off curl [thisrepo] [options]
+ setup curl config
git off integrity [thisrepo] [enable|disable]
set/show git off integrity.
when enabled, the SHA of the file received from the store is
@@ -177,7 +190,8 @@ git off help [cmd]
- nodejs
- git
-- ssh and scp for scp transport
+- ssh and scp for scp mode
+- curl for http mode
# Platforms
diff --git a/package.json b/package.json
@@ -1,6 +1,6 @@
{
"name": "git-off",
- "version": "0.0.5",
+ "version": "0.0.6",
"description": "large file handler for git",
"bin": "./src/git-off",
"scripts": {
diff --git a/src/git-off b/src/git-off
@@ -40,7 +40,7 @@
/*
* modules
*/
-var COMMAND_MAP, StringDecoder, copy, exec, expandHome, externalHelpers, fs, gitConfig, mkdirParents, mkdirp, offCommands, offDEFAULTS, offHelpers, offLog, offLogRepo, oiNAME, oiOID, oiPERMISSIONS, oiPREVIOUSOID, oiPREVIOUSPERMISSIONS, readline, rimraf, rmAll, runtimeConfig, showCommandHelp, syncexec, thisrepo, transport;
+var COMMAND_MAP, StringDecoder, copy, exec, expandHome, externalHelpers, fs, gitConfig, mkdirParents, mkdirp, offCommands, offDEFAULTS, offHelpers, offLog, offLogRepo, oiNAME, oiOID, oiPERMISSIONS, oiPREVIOUSOID, oiPREVIOUSPERMISSIONS, readline, rimraf, rmAll, runtimeConfig, showCommandHelp, syncexec, thisrepo, transport, walkSync;
require('colors');
@@ -81,13 +81,15 @@ externalHelpers = {
'sha': 'git hash-object --no-filters',
'listAttr': 'git check-attr -a',
'ssh': 'ssh',
- 'scp': 'scp'
+ 'scp': 'scp',
+ 'curl': 'curl'
};
runtimeConfig = {
'currentRepoRoot': '',
'objectPath': '',
'offStore': '',
+ 'offHttp': '',
'offMode': '',
'offIntegrity': '',
'offScp': '',
@@ -95,18 +97,25 @@ runtimeConfig = {
'offPem': '',
'offSshOptions': '',
'offScpOptions': '',
- 'log': ''
+ 'offCurlOptions': '',
+ 'log': '',
+ 'offConfigAlways': ''
};
offDEFAULTS = {
'objectPath': '/.git/off/objects',
'mode': 'copy',
'integrity': 'disable',
- 'pem': '',
+ 'pem': 'offNoValue',
+ 'scpHost': 'offNoValue',
+ 'scpUser': '',
'sshOptions': '-C -o StrictHostKeyChecking=no -o ConnectTimeout=3',
'scpOptions': '-C -o StrictHostKeyChecking=no -o ConnectTimeout=3 -p',
'store': '~/.git-off/offStore',
+ 'http': 'offNoValue',
+ 'curlOptions': '-o',
'log': '~/.git-off/log',
+ 'configAlways': 'offNoValue',
'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 "$@"',
'offSignature': '### git-off v1 sha:',
'shaLength': 40
@@ -136,21 +145,36 @@ gitConfig = {
},
'get': function(key) {
var r;
+ if (offHelpers.offConfigAlways() === 'GIT_OFF_CONFIG') {
+ r = '';
+ if (process.env.GIT_OFF_CONFIG !== void 0 && fs.existsSync(process.env.GIT_OFF_CONFIG) === true) {
+ r = exec('gitConfig', ['--file ' + process.env.GIT_OFF_CONFIG, key]).stdout.trim();
+ }
+ return r;
+ }
+ if (offHelpers.offConfigAlways() === 'repo') {
+ r = '';
+ if (fs.existsSync(offHelpers.gitRepoRoot(true) + '/.git-off') === true) {
+ r = exec('gitConfig', ['--file ' + offHelpers.gitRepoRoot() + '/.git-off', key]).stdout.trim();
+ }
+ return r;
+ }
+ if (offHelpers.offConfigAlways() === 'global') {
+ return exec('gitConfig', [key]).stdout.trim();
+ }
if (process.env.GIT_OFF_CONFIG !== void 0 && fs.existsSync(process.env.GIT_OFF_CONFIG) === true) {
r = exec('gitConfig', ['--file ' + process.env.GIT_OFF_CONFIG, key]).stdout.trim();
if (r !== '') {
return r;
}
}
- if (fs.existsSync(offHelpers.gitRepoRoot(true) + '/.git-off') === false) {
- return exec('gitConfig', [key]).stdout.trim();
- } else {
+ if (fs.existsSync(offHelpers.gitRepoRoot(true) + '/.git-off') === true) {
r = exec('gitConfig', ['--file ' + offHelpers.gitRepoRoot() + '/.git-off', key]).stdout.trim();
if (r !== '') {
return r;
}
- return exec('gitConfig', [key]).stdout.trim();
}
+ return exec('gitConfig', [key]).stdout.trim();
},
'getSyncexec': function(key) {
return syncexec(externalHelpers.gitConfig + ' ' + key);
@@ -209,6 +233,22 @@ copy = function(src, dst) {
fs.createReadStream(src).pipe(fs.createWriteStream(dst));
};
+walkSync = function(dir, filelist) {
+ var files;
+ if (filelist == null) {
+ filelist = [];
+ }
+ files = fs.readdirSync(dir);
+ files.forEach(function(file) {
+ if (fs.statSync(dir + '/' + file).isDirectory()) {
+ filelist = walkSync(dir + '/' + file, filelist);
+ } else {
+ filelist.push(dir + '/' + file);
+ }
+ });
+ return filelist;
+};
+
offHelpers = {
'gitRepoRoot': function(ignoreStderr) {
var r;
@@ -235,6 +275,18 @@ offHelpers = {
}
return runtimeConfig.offStore;
},
+ 'offHttp': function() {
+ if (runtimeConfig.offHttp === '') {
+ runtimeConfig.offHttp = gitConfig.get('off.http');
+ }
+ return runtimeConfig.offHttp;
+ },
+ 'offCurlOptions': function() {
+ if (runtimeConfig.offCurlOptions === '') {
+ runtimeConfig.offCurlOptions = gitConfig.get('off.curloptions');
+ }
+ return runtimeConfig.offCurlOptions;
+ },
'offMode': function() {
if (runtimeConfig.offMode === '') {
runtimeConfig.offMode = gitConfig.get('off.mode');
@@ -274,10 +326,8 @@ offHelpers = {
return runtimeConfig.offScp;
},
'offScpUser': function() {
- var r;
if (runtimeConfig.offScpUser === '') {
- r = gitConfig.get('off.scpuser');
- runtimeConfig.offScpUser = expandHome(r);
+ runtimeConfig.offScpUser = gitConfig.get('off.scpuser');
}
return runtimeConfig.offScpUser;
},
@@ -297,6 +347,14 @@ offHelpers = {
}
return runtimeConfig.log;
},
+ 'offConfigAlways': function() {
+ var r;
+ if (runtimeConfig.offConfigAlways === '') {
+ r = gitConfig.getSyncexec('off.configAlways');
+ runtimeConfig.offConfigAlways = r.stdout.trim();
+ }
+ return runtimeConfig.offConfigAlways;
+ },
'userAt': function() {
var user;
if (offHelpers.offScpUser() !== '') {
@@ -330,7 +388,7 @@ offHelpers = {
h_l = offHelpers.getSSHConfig();
sshCmd = '"mkdir -p ' + h_l[1] + '/' + path;
sshCmd += '"';
- if (offHelpers.offPem() === '') {
+ if (offHelpers.offPem() === '' || offHelpers.offPem() === 'offNoValue') {
pem = '';
} else {
pem = '-i ' + offHelpers.offPem();
@@ -343,7 +401,7 @@ offHelpers = {
},
'rmAllStore': function(path) {
var h_l, pem, sshCmd;
- if (offHelpers.offPem() === '') {
+ if (offHelpers.offPem() === '' || offHelpers.offPem() === 'offNoValue') {
pem = '';
} else {
pem = '-i ' + offHelpers.offPem();
@@ -357,6 +415,19 @@ offHelpers = {
exec('ssh', [offHelpers.offSshOptions(), pem, '-p ' + h_l[2], h_l[0], sshCmd], true);
}
},
+ 'copyTo': function() {
+ var f, files, i, j, len1, len2, tfiles;
+ tfiles = walkSync(offHelpers.objectPath());
+ files = [];
+ for (i = 0, len1 = tfiles.length; i < len1; i++) {
+ f = tfiles[i];
+ files.push(f.replace(offHelpers.objectPath() + '/', ''));
+ }
+ for (j = 0, len2 = files.length; j < len2; j++) {
+ f = files[j];
+ transport.send(f);
+ }
+ },
'checkIntegrity': function(path) {
var path_l, r, receivedSha, result;
result = true;
@@ -372,8 +443,14 @@ offHelpers = {
}
return result;
},
- 'setTransport': function() {
- if (offHelpers.offMode() === 'copy') {
+ 'setTransport': function(mode) {
+ if (mode == null) {
+ mode = 'config';
+ }
+ if (mode === 'config') {
+ mode = offHelpers.offMode();
+ }
+ if (mode === 'copy') {
transport['send'] = function(file) {
var f_l;
f_l = file.split('/');
@@ -390,12 +467,12 @@ offHelpers = {
readStream.pipe(process.stdout);
}
};
- } else if (offHelpers.offMode() === 'scp') {
+ } else if (mode === 'scp') {
transport['send'] = function(file) {
var f_l, h_l, pem;
f_l = file.split('/');
offHelpers.mkdirStore(f_l[0] + '/' + f_l[1]);
- if (offHelpers.offPem() === '') {
+ if (offHelpers.offPem() === '' || offHelpers.offPem() === 'offNoValue') {
pem = '';
} else {
pem = '-i ' + offHelpers.offPem();
@@ -413,7 +490,7 @@ offHelpers = {
if (fs.existsSync(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]) === false) {
mkdirParents(offHelpers.objectPath() + '/' + f_l[0] + '/' + f_l[1]);
}
- if (offHelpers.offPem() === '') {
+ if (offHelpers.offPem() === '' || offHelpers.offPem() === 'offNoValue') {
pem = '';
} else {
pem = '-i ' + offHelpers.offPem();
@@ -429,6 +506,22 @@ offHelpers = {
readStream.pipe(process.stdout);
}
};
+ } else if (mode === 'http') {
+ transport['send'] = function(file) {
+ offLogRepo('Http mode is read-only: ' + file + ' is stored in cache only');
+ };
+ transport['receive'] = function(file) {
+ var f_l, 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]);
+ }
+ exec('curl', [offHelpers.offCurlOptions(), offHelpers.objectPath() + '/' + file, offHelpers.offHttp() + '/' + file]);
+ if (offHelpers.checkIntegrity(offHelpers.objectPath() + '/' + file)) {
+ readStream = fs.createReadStream(offHelpers.objectPath() + '/' + file);
+ readStream.pipe(process.stdout);
+ }
+ };
}
},
'getOffFilePath': function(offFile) {
@@ -476,11 +569,7 @@ offCommands = {
}
}
if (offHelpers.log() === '' || setCfg !== gitConfig.set) {
- if (setCfg === gitConfig.setThisRepo) {
- gitConfig.setLocal('off.log', offDEFAULTS.log);
- } else {
- setCfg('off.log', offDEFAULTS.log);
- }
+ gitConfig.set('off.log', offDEFAULTS.log);
}
if (offHelpers.offMode() === '' || setCfg !== gitConfig.set) {
setCfg('off.mode', offDEFAULTS.mode);
@@ -491,6 +580,12 @@ offCommands = {
if (offHelpers.offPem() === '' || setCfg !== gitConfig.set) {
setCfg('off.pem', offDEFAULTS.pem);
}
+ if (offHelpers.offScp() === '' || setCfg !== gitConfig.set) {
+ setCfg('off.scphost', offDEFAULTS.scpHost);
+ }
+ if (offHelpers.offScpUser() === '' || setCfg !== gitConfig.set) {
+ setCfg('off.scpuser', offDEFAULTS.scpUser);
+ }
if (offHelpers.offSshOptions() === '' || setCfg !== gitConfig.set) {
setCfg('off.sshoptions', offDEFAULTS.sshOptions);
}
@@ -500,6 +595,15 @@ offCommands = {
if (offHelpers.offStore() === '' || setCfg !== gitConfig.set) {
setCfg('off.store', offDEFAULTS.store);
}
+ if (offHelpers.offHttp() === '' || setCfg !== gitConfig.set) {
+ setCfg('off.http', offDEFAULTS.http);
+ }
+ if (offHelpers.offCurlOptions() === '' || setCfg !== gitConfig.set) {
+ setCfg('off.curloptions', offDEFAULTS.curlOptions);
+ }
+ if (offHelpers.offConfigAlways() === '' || setCfg !== gitConfig.set) {
+ setCfg('off.configAlways', offDEFAULTS.configAlways);
+ }
if (runtimeConfig.offMode === 'copy') {
mkdirParents(runtimeConfig.offStore);
}
@@ -517,6 +621,16 @@ offCommands = {
console.log('off.mode '.blue.bold + offHelpers.offMode());
}
},
+ 'store': function(setCfg) {
+ var len, store;
+ len = process.argv.length;
+ store = process.argv[len - 1];
+ if (store !== 'store' && store !== 'thisrepo') {
+ setCfg('off.store', store);
+ } else {
+ console.log('off.store '.blue.bold + offHelpers.offStore());
+ }
+ },
'scp': function(setCfg) {
var len, scpHost;
len = process.argv.length;
@@ -527,6 +641,26 @@ offCommands = {
console.log('off.scp '.blue.bold + offHelpers.offScp());
}
},
+ 'http': function(setCfg) {
+ var http, len;
+ len = process.argv.length;
+ http = process.argv[len - 1];
+ if (http !== 'http' && http !== 'thisrepo') {
+ setCfg('off.http', http);
+ } else {
+ console.log('off.http '.blue.bold + offHelpers.offHttp());
+ }
+ },
+ 'curl': function(setCfg) {
+ var curl, len;
+ len = process.argv.length;
+ curl = process.argv[len - 1];
+ if (curl !== 'curl' && curl !== 'thisrepo') {
+ setCfg('off.curloptions', curl);
+ } else {
+ console.log('off.curloptions '.blue.bold + offHelpers.offCurlOptions());
+ }
+ },
'integrity': function(setCfg) {
var integrity, len;
len = process.argv.length;
@@ -593,6 +727,16 @@ offCommands = {
}
}
},
+ 'configAlways': function() {
+ var configAlways, len;
+ len = process.argv.length;
+ configAlways = process.argv[len - 1];
+ if (configAlways !== 'configAlways') {
+ gitConfig.set('off.configAlways', configAlways);
+ } else {
+ console.log('off.configAlways '.blue.bold + offHelpers.offConfigAlways());
+ }
+ },
'clean': function() {
var file, offFile, offFilePath, r, size, writeStream;
offCommands.localSetup();
@@ -692,18 +836,29 @@ offCommands = {
}
});
},
+ 'copyTo': function() {
+ if (process.argv[3] === void 0) {
+ console.log('Choose a mode where to copy the cache'.red.bold);
+ return;
+ }
+ offHelpers.setTransport(process.argv[3]);
+ offHelpers.copyTo();
+ },
'clearAll': function() {
+ offCommands.clearStore();
+ rmAll(offHelpers.objectPath());
+ rmAll(offHelpers.getLog());
+ },
+ 'clearCache': function() {
+ rmAll(offHelpers.objectPath());
+ },
+ 'clearStore': function() {
if (offHelpers.offMode() === 'copy') {
rmAll(offHelpers.offStore());
}
if (offHelpers.offMode() === 'scp') {
offHelpers.rmAllStore('');
}
- rmAll(offHelpers.objectPath());
- rmAll(offHelpers.getLog());
- },
- 'clearCache': function() {
- rmAll(offHelpers.objectPath());
},
'defaults': function() {
var i, k, len1, ref;
@@ -720,9 +875,12 @@ offCommands = {
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.http '.blue.bold + offHelpers.offHttp());
+ console.log('off.curloptions '.blue.bold + offHelpers.offCurlOptions());
console.log('off.scphost '.blue.bold + offHelpers.offScp());
console.log('off.scpuser '.blue.bold + offHelpers.offScpUser());
console.log('off.log '.blue.bold + offHelpers.getLog());
+ console.log('off.configAlways '.blue.bold + offHelpers.offConfigAlways());
},
'help': function() {
var c, i, len1, ref;
@@ -792,7 +950,13 @@ COMMAND_MAP = {
f: function() {
thisrepo(offCommands['mode']);
},
- h: 'git off mode [thisrepo] [copy|scp]\n set/show git off mode'
+ h: 'git off mode [thisrepo] [copy|scp|http]\n set/show git off mode'
+ },
+ 'store': {
+ f: function() {
+ thisrepo(offCommands['store']);
+ },
+ h: 'git off store [thisrepo] [path]\n set/show git off store path for copy mode'
},
'scp': {
f: function() {
@@ -800,6 +964,18 @@ COMMAND_MAP = {
},
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'
},
+ 'http': {
+ f: function() {
+ thisrepo(offCommands['http']);
+ },
+ h: 'git off http [thisrepo] [host]\n setup http config\n host has format http://host/path\n Example: http://localhost/offStore'
+ },
+ 'curl': {
+ f: function() {
+ thisrepo(offCommands['curl']);
+ },
+ h: 'git off curl [thisrepo] [options]\n setup curl config'
+ },
'integrity': {
f: function() {
thisrepo(offCommands['integrity']);
@@ -810,7 +986,7 @@ COMMAND_MAP = {
f: function() {
thisrepo(offCommands['pem']);
},
- h: 'git off pem [thisrepo] [pathToPrivateKey]\n set/show git off pem.\n off.pem is the private key for ssh and scp'
+ h: "git off pem [thisrepo] [pathToPrivateKey]\n set/show git off pem.\n off.pem is the private key for ssh and scp\n set 'offNoValue' to set an empty value (useful when there are multiple configs)"
},
'sshoptions': {
f: function() {
@@ -836,6 +1012,12 @@ COMMAND_MAP = {
},
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"
},
+ 'configAlways': {
+ f: function() {
+ offCommands.configAlways();
+ },
+ 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"
+ },
'clean': {
f: function() {
offCommands.clean();
@@ -854,6 +1036,12 @@ COMMAND_MAP = {
},
h: 'git off smudge\n internal filter\n dont use directly'
},
+ 'copyTo': {
+ f: function() {
+ offCommands.copyTo();
+ },
+ h: 'git off copyTo [copy|scp]\n copy cache to store for specified mode'
+ },
'clearAll': {
f: function() {
offCommands.clearAll();
@@ -878,6 +1066,18 @@ COMMAND_MAP = {
},
h: 'git off cc\n delete cache in current git'
},
+ 'clearStore': {
+ f: function() {
+ offCommands.clearStore();
+ },
+ h: 'git off clearStore\n delete store'
+ },
+ 'cs': {
+ f: function() {
+ offCommands.clearStore();
+ },
+ h: 'git off cs\n delete store'
+ },
'defaults': {
f: function() {
offCommands.defaults();
diff --git a/src/gitoff.coffee b/src/gitoff.coffee
@@ -105,6 +105,7 @@ externalHelpers =
'listAttr': 'git check-attr -a'
'ssh': 'ssh'
'scp': 'scp'
+ 'curl': 'curl'
# config built by offHelpers
# use offHelpers to access runtimeConfig
@@ -112,6 +113,7 @@ runtimeConfig =
'currentRepoRoot': ''
'objectPath': ''
'offStore': ''
+ 'offHttp': ''
'offMode': ''
'offIntegrity': ''
'offScp': ''
@@ -119,6 +121,7 @@ runtimeConfig =
'offPem': ''
'offSshOptions': ''
'offScpOptions': ''
+ 'offCurlOptions': ''
'log': ''
'offConfigAlways': ''
@@ -129,9 +132,13 @@ offDEFAULTS =
'mode': 'copy'
'integrity': 'disable'
'pem': 'offNoValue'
+ 'scpHost': 'offNoValue'
+ 'scpUser': ''
'sshOptions': '-C -o StrictHostKeyChecking=no -o ConnectTimeout=3'
'scpOptions': '-C -o StrictHostKeyChecking=no -o ConnectTimeout=3 -p'
'store': '~/.git-off/offStore'
+ 'http': 'offNoValue'
+ 'curlOptions': '-o'
'log': '~/.git-off/log'
'configAlways': 'offNoValue'
'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 "$@"'
@@ -303,6 +310,16 @@ offHelpers =
runtimeConfig.offStore = expandHome r
runtimeConfig.offStore
+ 'offHttp': ->
+ if runtimeConfig.offHttp == ''
+ runtimeConfig.offHttp = gitConfig.get 'off.http'
+ runtimeConfig.offHttp
+
+ 'offCurlOptions': ->
+ if runtimeConfig.offCurlOptions == ''
+ runtimeConfig.offCurlOptions = gitConfig.get 'off.curloptions'
+ runtimeConfig.offCurlOptions
+
'offMode': ->
if runtimeConfig.offMode == ''
runtimeConfig.offMode = gitConfig.get 'off.mode'
@@ -478,6 +495,7 @@ offHelpers =
if mode == 'config'
mode = offHelpers.offMode()
+ # copy mode
if mode == 'copy'
transport['send'] = (file) ->
# create file directories in store
@@ -494,6 +512,7 @@ offHelpers =
readStream.pipe(process.stdout)
return
+ # scp mode
else if mode == 'scp'
transport['send'] = (file) ->
@@ -535,6 +554,24 @@ offHelpers =
readStream = fs.createReadStream(offHelpers.objectPath() + '/' + file)
readStream.pipe(process.stdout)
return
+
+ # copy http
+ else if mode == 'http'
+ transport['send'] = (file) ->
+ offLogRepo('Http mode is read-only: ' + file + ' is stored in cache only')
+ return
+ transport['receive'] = (file) ->
+ # create file directories in cache
+ 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]
+
+ exec 'curl', [offHelpers.offCurlOptions(), offHelpers.objectPath() + '/' + file, offHelpers.offHttp() + '/' + file]
+
+ if offHelpers.checkIntegrity offHelpers.objectPath() + '/' + file
+ readStream = fs.createReadStream(offHelpers.objectPath() + '/' + file)
+ readStream.pipe(process.stdout)
+ return
return
'getOffFilePath': (offFile) ->
@@ -617,12 +654,20 @@ offCommands =
setCfg('off.integrity', offDEFAULTS.integrity)
if offHelpers.offPem() == '' or setCfg != gitConfig.set
setCfg('off.pem', offDEFAULTS.pem)
+ if offHelpers.offScp() == '' or setCfg != gitConfig.set
+ setCfg('off.scphost', offDEFAULTS.scpHost)
+ if offHelpers.offScpUser() == '' or setCfg != gitConfig.set
+ setCfg('off.scpuser', offDEFAULTS.scpUser)
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)
+ if offHelpers.offHttp() == '' or setCfg != gitConfig.set
+ setCfg('off.http', offDEFAULTS.http)
+ if offHelpers.offCurlOptions() == '' or setCfg != gitConfig.set
+ setCfg('off.curloptions', offDEFAULTS.curlOptions)
if offHelpers.offConfigAlways() == '' or setCfg != gitConfig.set
setCfg('off.configAlways', offDEFAULTS.configAlways)
@@ -644,6 +689,15 @@ offCommands =
console.log 'off.mode '.blue.bold + offHelpers.offMode()
return
+ 'store': (setCfg) ->
+ len = process.argv.length
+ store = process.argv[len-1]
+ if store != 'store' and store != 'thisrepo'
+ setCfg('off.store', store)
+ else
+ console.log 'off.store '.blue.bold + offHelpers.offStore()
+ return
+
'scp': (setCfg) ->
len = process.argv.length
scpHost = process.argv[len-1]
@@ -653,6 +707,24 @@ offCommands =
console.log 'off.scp '.blue.bold + offHelpers.offScp()
return
+ 'http': (setCfg) ->
+ len = process.argv.length
+ http = process.argv[len-1]
+ if http != 'http' and http != 'thisrepo'
+ setCfg('off.http', http)
+ else
+ console.log 'off.http '.blue.bold + offHelpers.offHttp()
+ return
+
+ 'curl': (setCfg) ->
+ len = process.argv.length
+ curl = process.argv[len-1]
+ if curl != 'curl' and curl != 'thisrepo'
+ setCfg('off.curloptions', curl)
+ else
+ console.log 'off.curloptions '.blue.bold + offHelpers.offCurlOptions()
+ return
+
'integrity': (setCfg) ->
len = process.argv.length
integrity = process.argv[len-1]
@@ -936,6 +1008,8 @@ offCommands =
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.http '.blue.bold + offHelpers.offHttp()
+ console.log 'off.curloptions '.blue.bold + offHelpers.offCurlOptions()
console.log 'off.scphost '.blue.bold + offHelpers.offScp()
console.log 'off.scpuser '.blue.bold + offHelpers.offScpUser()
console.log 'off.log '.blue.bold + offHelpers.getLog()
@@ -1008,7 +1082,13 @@ COMMAND_MAP =
f: ->
thisrepo offCommands['mode']
return
- h: 'git off mode [thisrepo] [copy|scp]\n set/show git off mode'
+ h: 'git off mode [thisrepo] [copy|scp|http]\n set/show git off mode'
+
+ 'store':
+ f: ->
+ thisrepo offCommands['store']
+ return
+ h: 'git off store [thisrepo] [path]\n set/show git off store path for copy mode'
'scp':
f: ->
@@ -1016,6 +1096,18 @@ COMMAND_MAP =
return
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'
+ 'http':
+ f: ->
+ thisrepo offCommands['http']
+ return
+ h: 'git off http [thisrepo] [host]\n setup http config\n host has format http://host/path\n Example: http://localhost/offStore'
+
+ 'curl':
+ f: ->
+ thisrepo offCommands['curl']
+ return
+ h: 'git off curl [thisrepo] [options]\n setup curl config'
+
'integrity':
f: ->
thisrepo offCommands['integrity']