summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@gmail.com>2013-11-06 22:55:16 +0000
committerRichard Maw <richard.maw@gmail.com>2013-11-06 22:58:12 +0000
commit4c938c5654e83d148c7f546b4f0a14c04047bc9c (patch)
tree9a264a6533f33637717416681c960158f758b2c1
parentba61e4d81d6113a19a62726619713bb491e21a56 (diff)
downloadtar-clone-4c938c5654e83d148c7f546b4f0a14c04047bc9c.tar.bz2
Allow index creation
-rwxr-xr-xtar-clone2
-rwxr-xr-xtar-clone.lua79
2 files changed, 79 insertions, 2 deletions
diff --git a/tar-clone b/tar-clone
index ebc21b1..6fc3315 100755
--- a/tar-clone
+++ b/tar-clone
@@ -14,5 +14,3 @@ export LUA_CPATH
SOURCE="$1"
TARGET="$2"
$LUA "$CURDIR/tar-clone.lua" "$SOURCE" "$TARGET" | tar x
-cd "$TARGET"
-git reset HEAD
diff --git a/tar-clone.lua b/tar-clone.lua
index a5fc692..6ced918 100755
--- a/tar-clone.lua
+++ b/tar-clone.lua
@@ -6,6 +6,40 @@ local sio = require "luxio.simple"
local sp = require "luxio.subprocess"
local archive = require "archive"
+local function make_temp(syscall, template, tempdir)
+ template = template or "tmp.XXXXXX"
+ tempdir = tempdir or os.getenv("TMPDIR") or "/tmp"
+ local retries = 100
+ if not template:find('/') then
+ template = tempdir..'/'..template
+ end
+ if template:sub(-6) ~= "XXXXXX" then
+ error("Template must end in XXXXXX")
+ end
+ repeat
+ local tempname = template:sub(1, -7)..tostring(math.random(999999))
+ local ret = {syscall(tempname)}
+ local ok = table.remove(ret, 1)
+ if ok then
+ return tempname, unpack(ret)
+ end
+ retries = retries - 1
+ until retries == 0
+ error("Unable to create temporary")
+end
+local function mkdtemp(template, tempdir)
+ return make_temp(function(tempname)
+ local ret, errmsg, errno = sio.mkdir(tempname, "0700")
+ if ret == 0 then
+ return tempname
+ end
+ if errno == luxio.EEXIST then
+ return false
+ end
+ error(("Failed to make directory %s: %s"):format(tempname, errmsg))
+ end, template, tempdir)
+end
+
local CONFIG_FORMAT = [[
[core]
repositoryformatversion = 0
@@ -187,6 +221,49 @@ local function write_workspace(writer, repo, HEAD, localname, bufsize)
end
end
+local function list_tree(repo, HEAD)
+ local proc = sp.spawn_simple{"git", "ls-tree", "-rz", HEAD,
+ cwd = repo, stdout = sp.PIPE}
+ local output = proc.stdout:read("*a")
+ return output:gmatch"([^ ]+) ([^ ]+) ([^ ]+)\t([^%z]+)%z"
+end
+
+local function write_index(writer, repo, HEAD, localname)
+ local cmdline = {"git", "update-index", "--add"}
+ for mode, kind, sha1, path in list_tree(repo, HEAD) do
+ table.insert(cmdline, "--cacheinfo")
+ table.insert(cmdline, mode)
+ table.insert(cmdline, sha1)
+ table.insert(cmdline, path)
+ end
+ local dir = mkdtemp()
+ local index = dir..'/index'
+
+ cmdline.cwd = repo
+ cmdline.env = {GIT_INDEX_FILE = index}
+ local proc = sp.spawn_simple(cmdline)
+ local how, why = proc:wait()
+ if how == -1 then
+ error("git update-index failed: "..tostring(why))
+ end
+ local entry = archive.entry{
+ sourcepath = index,
+ pathname = localname..'/.git/index',
+ ino = 0,
+ dev = 0,
+ uid = 0,
+ uname = 'root',
+ gid = 0,
+ gname = 'root',
+ atime = {683074800, 683074800},
+ ctime = {683074800, 683074800},
+ mtime = {683074800, 683074800},
+ birthtime = {683074800, 683074800},
+ }
+ writer:header(entry)
+ copy_file(index, function(data) writer:data(data) end)
+end
+
local writer = archive.write{
format = "pax",
writer = function(archive, string)
@@ -210,3 +287,5 @@ write_file(writer, localname..'/.git/config', config)
write_refs(writer, repo, HEAD, localname)
write_workspace(writer, repo, HEAD, localname)
+
+write_index(writer, repo, HEAD, localname)