{"thread":{"id":"18532","subject":"[PATCH 2/2] init: support --fast-import using \"git fast-import\" as backend","startedAt":"2009-03-25T11:01:39Z","lastAt":"2009-03-25T11:01:39Z","messageCount":1,"participants":["Nguyễn Thái Ngọc Duy"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"109337","messageId":"1237978899-2621-1-git-send-email-pclouds@gmail.com","threadId":"18532","inReplyTo":null,"subject":"[PATCH 2/2] init: support --fast-import using \"git fast-import\" as backend","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2009-03-25T11:01:39Z","receivedAt":"2009-03-25T11:01:39Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"I was curious to see how git-import script performed in C version.\nThe result is quite good (only tried once so might be incorrect).\nThe patch is not ready for submission though. Sorry for patch numbering,\nforgot to add \"-n\".\n\nTests were performed with \"echo 3 > /proc/sys/vm/drop_caches\". Test repo is\ngentoo-x86, which consists of ~11k small text files.\n\n~/t/gentoo-x86 $ time ~/git/git/git init -M\nInitialized empty Git repository in /home/pclouds/t/gentoo-x86/.git/\n\nreal    7m30.663s\nuser    0m33.171s\nsys     3m31.599s\n~/t/gentoo-x86 $ du -s .git\n73700   .git\n~/t/gentoo-x86 $ find .git/|wc -l\n31\n~/t/gentoo-x86 $ git ls-files|wc -l\n113012\n\n~/t/gentoo-x86 $ rm .git/ -rf\n~/t/gentoo-x86 $ time ~/git/git/git init -m\nInitialized empty Git repository in /home/pclouds/t/gentoo-x86/.git/\n\nreal    10m5.114s\nuser    0m13.718s\nsys     3m50.317s\n~/t/gentoo-x86 $ du -s .git\n521960  .git\n~/t/gentoo-x86 $ find .git/|wc -l\n123275\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin-init-db.c |  108 +++++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 files changed, 105 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin-init-db.c b/builtin-init-db.c\nindex 3ace4ca..42c126c 100644\n--- a/builtin-init-db.c\n+++ b/builtin-init-db.c\n@@ -386,6 +386,105 @@ static int import_files(const char *import_message)\n \treturn run_command_v_opt(args, RUN_GIT_CMD);\n }\n \n+static void fast_import_recursive(int fdo, const char *path)\n+{\n+\tDIR *fdir;\n+\tchar fullname[PATH_MAX + 1];\n+\tint len, dtype, fdi;\n+\tstruct dirent *de;\n+\tstruct stat st;\n+\tconst char *fdir_path;\n+\tchar buf[4096];\n+\tint buflen;\n+\tstruct strbuf s;\n+\n+\tfdir_path = path ? path : \".\";\n+\tfdir = opendir(fdir_path);\n+\tif (!fdir)\n+\t\tdie(\"Could not open directory %s\", fdir_path);\n+\n+\tif (path) {\n+\t\tlen = strlen(path);\n+\t\tmemcpy(fullname, path, len);\n+\t\tfullname[len++] = '/';\n+\t}\n+\telse\n+\t\tlen = 0;\n+\tstrbuf_init(&s, 32);\n+\twhile ((de = readdir(fdir)) != NULL) {\n+\t\tif (!strcmp(de->d_name, \".\") ||\n+\t\t    !strcmp(de->d_name, \"..\") ||\n+\t\t    !strcmp(de->d_name, \".git\"))\n+\t\t\tcontinue;\n+\t\tdtype = DTYPE(de);\n+\t\tmemcpy(fullname+len, de->d_name, de->d_reclen+1);\n+\t\tif (lstat(fullname, &st))\n+\t\t\tdie(\"Could not stat %s\", fullname);\n+\t\tif (dtype == DT_UNKNOWN) {\n+\t\t\tif (S_ISREG(st.st_mode))\n+\t\t\t\tdtype = DT_REG;\n+\t\t\tif (S_ISDIR(st.st_mode))\n+\t\t\t\tdtype = DT_DIR;\n+\t\t\tif (S_ISLNK(st.st_mode))\n+\t\t\t\tdtype = DT_LNK;\n+\t\t}\n+\t\tswitch (dtype) {\n+\t\tcase DT_DIR:\n+\t\t\tfast_import_recursive(fdo, fullname);\n+\t\t\tbreak;\n+\t\tcase DT_LNK:\n+\t\tcase DT_REG:\n+\t\t\tfdi = open(fullname, O_RDONLY);\n+\t\t\tif (fdi == -1)\n+\t\t\t\tdie(\"Could not open %s\", fullname);\n+\t\t\tstrbuf_setlen(&s, 0);\n+\t\t\tstrbuf_addf(&s,\"M 100644 inline %s\\n\", fullname);\n+\t\t\tstrbuf_addf(&s, \"data %u\\n\", (unsigned int)st.st_size); /* FIXME: large file */\n+\t\t\twrite_or_die(fdo, s.buf, s.len);\n+\t\t\twhile ((buflen = xread(fdi, buf, sizeof(buf))) > 0)\n+\t\t\t\twrite_or_die(fdo, buf, buflen);\n+\t\t\tclose(fdi);\n+\t\t\twrite_or_die(fdo, \"\\n\", 1);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tstrbuf_release(&s);\n+\tclosedir(fdir);\n+}\n+\n+#define FAST_IMPORT_DEBUG 0\n+\n+static int fast_import_files(const char *import_message)\n+{\n+\tstruct child_process p;\n+\tconst char *argv[4] = {\"fast-import\", \"--quiet\", \"--date-format=raw\", NULL};\n+\tstruct strbuf s;\n+\n+\tmemset(&p, 0, sizeof(p));\n+\tp.argv = argv;\n+\tp.in = -1;\n+\tp.git_cmd = 1;\n+#if FAST_IMPORT_DEBUG\n+\tp.in = 1;\n+#else\n+\tif (start_command(&p))\n+\t\tdie(\"Could not spawn fast-import\");\n+#endif\n+\tstrbuf_init(&s, 64);\n+\tstrbuf_addstr(&s, \"commit refs/heads/master\\n\");\n+\tstrbuf_addf(&s,   \"committer %s\\n\", git_committer_info(0));\n+\tstrbuf_addf(&s,   \"data <<MSGEND\\n%s\\nMSGEND\\n\", import_message);\n+\twrite_or_die(p.in, s.buf, s.len);\n+\tstrbuf_release(&s);\n+\tfast_import_recursive(p.in, NULL);\n+#if !FAST_IMPORT_DEBUG\n+\tclose(p.in);\n+\tif (finish_command(&p))\n+\t\tdie(\"fast-import died\");\n+#endif\n+\treturn 0;\n+}\n+\n static const char init_db_usage[] =\n \"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]] [-m|--import [<message>]]\";\n \n@@ -401,7 +500,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)\n \tconst char *template_dir = NULL;\n \tunsigned int flags = 0;\n \tconst char *import_message = NULL;\n-\tint ret, i;\n+\tint ret, i, fast_import = 0;\n \n \tfor (i = 1; i < argc; i++, argv++) {\n \t\tconst char *arg = argv[1];\n@@ -416,7 +515,10 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)\n \t\t\tinit_shared_repository = PERM_GROUP;\n \t\telse if (!prefixcmp(arg, \"--shared=\"))\n \t\t\tinit_shared_repository = git_config_perm(\"arg\", arg+9);\n-\t\telse if (!strcmp(arg, \"--import\") || !strcmp(arg, \"-m\")) {\n+\t\telse if (!strcmp(arg, \"--import\") || !strcmp(arg, \"-m\") ||\n+\t\t\t !strcmp(arg, \"--fast-import\") || !strcmp(arg, \"-M\")) {\n+\t\t\tif (!strcmp(arg, \"--fast-import\") || !strcmp(arg, \"-M\"))\n+\t\t\t\tfast_import = 1;\n \t\t\tif (i+1 >= argc)\n \t\t\t\timport_message = \"Initial commit\";\n \t\t\telse {\n@@ -481,5 +583,5 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)\n \t\treturn ret;\n \tif (reinit)\n \t\tdie(\"--import does not work with already initialized repository\");\n-\treturn import_files(import_message);\n+\treturn fast_import ? fast_import_files(import_message) : import_files(import_message);\n }\n-- \n1.6.1.446.gc7851\n"}]}