git-off

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

commit 610a377d1eb8851ea15c62eb4c55d1b950ca9f33
parent a4a00722c60a3a834f6bcc3a0ce3b15c2f1ba880
Author: Remy Noulin <loader2x@gmail.com>
Date:   Wed, 19 Jul 2017 16:36:57 +0200

handle empty cloned gits

c/git-off.c       | 18 ++++++++++++++----
c/gitoff.c        | 18 ++++++++++++++----
src/git-off       | 10 ++++++++--
src/gitoff.coffee | 26 ++++++++++++++++----------
4 files changed, 52 insertions(+), 20 deletions(-)

Diffstat:
Mc/git-off.c | 18++++++++++++++----
Mc/gitoff.c | 18++++++++++++++----
Msrc/git-off | 10++++++++--
Msrc/gitoff.coffee | 26++++++++++++++++----------
4 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/c/git-off.c b/c/git-off.c @@ -228,7 +228,7 @@ int argc; char **argv; // shell commands to be used with the exec function // example: exec 'gitRepoRoot' enum { gitConfigGlobal, gitConfig, gitRepoRoot, gitList, gitDff, gitCat, sha, listAttr, ssh, scp, rsync, curl, mv, mkdirE, cp, rm }; -char* externalHelpers[16] = { "git config --global", "git config", "git rev-parse --show-toplevel", "git rev-list", "git diff-tree -r", "git cat-file -p", "git hash-object --no-filters", "git check-attr -a", "ssh", "scp", "rsync", "curl", "mv", "mkdir -p", "cp -u", "rm -rf" }; +char* externalHelpers[16] = { "git config --global", "git config", "git rev-parse --show-toplevel", "git rev-list", "git show --raw --format=\"\" --no-abbrev", "git cat-file -p", "git hash-object --no-filters", "git check-attr -a", "ssh", "scp", "rsync", "curl", "mv", "mkdir -p", "cp -u", "rm -rf" }; // config built by offHelpers // use offHelpers to access runtimeConfig @@ -2184,9 +2184,19 @@ void offCommands_push(char *line) { remoteSha = line_l[3]; // list missing commits in remote - cmd = malloc(strlen(externalHelpers[gitList]) + strlen(localSha) + strlen(remoteSha) + 1 + 3); - sprintf(cmd, "%s %s ^%s", externalHelpers[gitList], localSha, remoteSha); - commitListToPush = execOut(cmd); + // handle empty cloned repo + if (strEq(remoteSha, "0000000000000000000000000000000000000000")) { + // run git rev-list --max-parents=0 localSha + // when an empty git was cloned. + char *parent = "--max-parents=0";; + cmd = malloc(strlen(externalHelpers[gitList]) + strlen(parent) + strlen(localSha) + 1 + 3);; + sprintf(cmd, "%s %s %s", externalHelpers[gitList], parent, localSha); + } + else { + cmd = malloc(strlen(externalHelpers[gitList]) + strlen(localSha) + strlen(remoteSha) + 1 + 3); + sprintf(cmd, "%s %s ^%s", externalHelpers[gitList], localSha, remoteSha); + commitListToPush = execOut(cmd); + } free(cmd); // list changed objects in missing commits diff --git a/c/gitoff.c b/c/gitoff.c @@ -227,7 +227,7 @@ int argc; char **argv; // shell commands to be used with the exec function // example: exec 'gitRepoRoot' enum { gitConfigGlobal, gitConfig, gitRepoRoot, gitList, gitDff, gitCat, sha, listAttr, ssh, scp, rsync, curl, mv, mkdirE, cp, rm }; -char* externalHelpers[16] = { "git config --global", "git config", "git rev-parse --show-toplevel", "git rev-list", "git diff-tree -r", "git cat-file -p", "git hash-object --no-filters", "git check-attr -a", "ssh", "scp", "rsync", "curl", "mv", "mkdir -p", "cp -u", "rm -rf" }; +char* externalHelpers[16] = { "git config --global", "git config", "git rev-parse --show-toplevel", "git rev-list", "git show --raw --format=\"\" --no-abbrev", "git cat-file -p", "git hash-object --no-filters", "git check-attr -a", "ssh", "scp", "rsync", "curl", "mv", "mkdir -p", "cp -u", "rm -rf" }; // config built by offHelpers // use offHelpers to access runtimeConfig @@ -2183,9 +2183,19 @@ void offCommands_push(char *line) { remoteSha = line_l[3]; // list missing commits in remote - cmd = malloc(strlen(externalHelpers[gitList]) + strlen(localSha) + strlen(remoteSha) + 1 + 3); - sprintf(cmd, "%s %s ^%s", externalHelpers[gitList], localSha, remoteSha); - commitListToPush = execOut(cmd); + // handle empty cloned repo + if (strEq(remoteSha, "0000000000000000000000000000000000000000")) { + // run git rev-list --max-parents=0 localSha + // when an empty git was cloned. + char *parent = "--max-parents=0";; + cmd = malloc(strlen(externalHelpers[gitList]) + strlen(parent) + strlen(localSha) + 1 + 3);; + sprintf(cmd, "%s %s %s", externalHelpers[gitList], parent, localSha); + } + else { + cmd = malloc(strlen(externalHelpers[gitList]) + strlen(localSha) + strlen(remoteSha) + 1 + 3); + sprintf(cmd, "%s %s ^%s", externalHelpers[gitList], localSha, remoteSha); + commitListToPush = execOut(cmd); + } free(cmd); // list changed objects in missing commits diff --git a/src/git-off b/src/git-off @@ -80,7 +80,8 @@ externalHelpers = { 'gitConfig': 'git config', 'gitRepoRoot': 'git rev-parse --show-toplevel', 'gitList': 'git rev-list', - 'gitDiff': 'git diff-tree -r', + 'gitListEmptyRemote': 'git rev-list --max-parents=0', + 'gitDiff': 'git show --raw --format="" --no-abbrev', 'gitCat': 'git cat-file -p', 'sha': 'git hash-object --no-filters', 'listAttr': 'git check-attr -a', @@ -1063,7 +1064,12 @@ offCommands = { localSha = line_l[1]; remoteRef = line_l[2]; remoteSha = line_l[3]; - r = exec('gitList', [localSha, '^' + remoteSha]); + r = 0; + if (remoteSha === '0000000000000000000000000000000000000000') { + r = exec('gitListEmptyRemote', [localSha]); + } else { + r = exec('gitList', [localSha, '^' + remoteSha]); + } commitListToPush = r.stdout.split('\n'); commitListToPush = commitListToPush.slice(0, commitListToPush.length - 1); for (i = 0, len1 = commitListToPush.length; i < len1; i++) { diff --git a/src/gitoff.coffee b/src/gitoff.coffee @@ -101,7 +101,8 @@ externalHelpers = 'gitConfig': 'git config' 'gitRepoRoot': 'git rev-parse --show-toplevel' 'gitList': 'git rev-list' - 'gitDiff': 'git diff-tree -r' + 'gitListEmptyRemote': 'git rev-list --max-parents=0' + 'gitDiff': 'git show --raw --format="" --no-abbrev' 'gitCat': 'git cat-file -p' 'sha': 'git hash-object --no-filters' 'listAttr': 'git check-attr -a' @@ -515,7 +516,7 @@ offHelpers = # check integrity of files coming from the store result = true - + if offHelpers.offIntegrity() == 'disable' return true @@ -583,7 +584,7 @@ offHelpers = # setup ssh/scp private key if offHelpers.offPem() != '' and offHelpers.offPem() != 'offNoValue' options = options.replace '_i', offHelpers.offPem() - + exec 'rsync', [options, offHelpers.objectPath() + '/' + file, offHelpers.offScp() + '/' + file] return transport['receive'] = (file) -> @@ -599,7 +600,7 @@ offHelpers = # setup ssh/scp private key if offHelpers.offPem() != '' and offHelpers.offPem() != 'offNoValue' options = options.replace '_i', offHelpers.offPem() - + exec 'rsync', [options, offHelpers.offScp() + '/' + file, offHelpers.objectPath() + '/' + file] # transform @@ -867,7 +868,7 @@ offCommands = setCfg('off.transformFrom', offDEFAULTS.transformFrom) # create off.store - + if runtimeConfig.offMode == 'copy' mkdirParents runtimeConfig.offStore @@ -982,7 +983,7 @@ offCommands = fs.appendFileSync(offHelpers.gitRepoRoot() + '/.gitattributes', process.argv[3] + ' filter=off -text\n') else # list current git off attributes - + r = exec 'listAttr', ['`cd ' + offHelpers.gitRepoRoot() + '; git ls-files`'] # gff/b.bin: filter: off for l in r.stdout.split('\n') @@ -1146,11 +1147,16 @@ offCommands = remoteSha = line_l[3] # list missing commits in remote - r = exec 'gitList', [localSha, '^' + remoteSha] + r = 0 + # handle empty cloned repo + if remoteSha == '0000000000000000000000000000000000000000' + r = exec 'gitListEmptyRemote', [localSha] + else + r = exec 'gitList', [localSha, '^' + remoteSha] commitListToPush = r.stdout.split('\n') # remove last empty line commitListToPush = commitListToPush.slice(0, commitListToPush.length-1) - + # list changed objects in missing commits for sha in commitListToPush @@ -1164,10 +1170,10 @@ offCommands = for oi in objInfoList objInfo = oi.split(' ') - + # dont consider deleted files if objInfo[oiNAME].slice(0,1) != 'D' - + # check header with git cat r = exec 'gitCat', [objInfo[oiOID]]