Merge branch 'db/svn-fe-code-purge' into svn-fe
* db/svn-fe-code-purge: vcs-svn: drop obj_pool vcs-svn: drop treap vcs-svn: drop string_pool vcs-svn: pass paths through to fast-import Conflicts: vcs-svn/fast_export.c vcs-svn/fast_export.h vcs-svn/repo_tree.c vcs-svn/repo_tree.h vcs-svn/string_pool.c vcs-svn/svndump.c vcs-svn/trp.txt
This commit is contained in:
commit
c19d653c4f
3
.gitignore
vendored
3
.gitignore
vendored
@ -169,16 +169,13 @@
|
|||||||
/test-line-buffer
|
/test-line-buffer
|
||||||
/test-match-trees
|
/test-match-trees
|
||||||
/test-mktemp
|
/test-mktemp
|
||||||
/test-obj-pool
|
|
||||||
/test-parse-options
|
/test-parse-options
|
||||||
/test-path-utils
|
/test-path-utils
|
||||||
/test-run-command
|
/test-run-command
|
||||||
/test-sha1
|
/test-sha1
|
||||||
/test-sigchain
|
/test-sigchain
|
||||||
/test-string-pool
|
|
||||||
/test-subprocess
|
/test-subprocess
|
||||||
/test-svn-fe
|
/test-svn-fe
|
||||||
/test-treap
|
|
||||||
/common-cmds.h
|
/common-cmds.h
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.dsc
|
*.dsc
|
||||||
|
13
Makefile
13
Makefile
@ -425,16 +425,13 @@ TEST_PROGRAMS_NEED_X += test-dump-cache-tree
|
|||||||
TEST_PROGRAMS_NEED_X += test-genrandom
|
TEST_PROGRAMS_NEED_X += test-genrandom
|
||||||
TEST_PROGRAMS_NEED_X += test-line-buffer
|
TEST_PROGRAMS_NEED_X += test-line-buffer
|
||||||
TEST_PROGRAMS_NEED_X += test-match-trees
|
TEST_PROGRAMS_NEED_X += test-match-trees
|
||||||
TEST_PROGRAMS_NEED_X += test-obj-pool
|
|
||||||
TEST_PROGRAMS_NEED_X += test-parse-options
|
TEST_PROGRAMS_NEED_X += test-parse-options
|
||||||
TEST_PROGRAMS_NEED_X += test-path-utils
|
TEST_PROGRAMS_NEED_X += test-path-utils
|
||||||
TEST_PROGRAMS_NEED_X += test-run-command
|
TEST_PROGRAMS_NEED_X += test-run-command
|
||||||
TEST_PROGRAMS_NEED_X += test-sha1
|
TEST_PROGRAMS_NEED_X += test-sha1
|
||||||
TEST_PROGRAMS_NEED_X += test-sigchain
|
TEST_PROGRAMS_NEED_X += test-sigchain
|
||||||
TEST_PROGRAMS_NEED_X += test-string-pool
|
|
||||||
TEST_PROGRAMS_NEED_X += test-subprocess
|
TEST_PROGRAMS_NEED_X += test-subprocess
|
||||||
TEST_PROGRAMS_NEED_X += test-svn-fe
|
TEST_PROGRAMS_NEED_X += test-svn-fe
|
||||||
TEST_PROGRAMS_NEED_X += test-treap
|
|
||||||
TEST_PROGRAMS_NEED_X += test-index-version
|
TEST_PROGRAMS_NEED_X += test-index-version
|
||||||
TEST_PROGRAMS_NEED_X += test-mktemp
|
TEST_PROGRAMS_NEED_X += test-mktemp
|
||||||
|
|
||||||
@ -1837,10 +1834,9 @@ ifndef NO_CURL
|
|||||||
endif
|
endif
|
||||||
XDIFF_OBJS = xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
|
XDIFF_OBJS = xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
|
||||||
xdiff/xmerge.o xdiff/xpatience.o
|
xdiff/xmerge.o xdiff/xpatience.o
|
||||||
VCSSVN_OBJS = vcs-svn/string_pool.o vcs-svn/line_buffer.o \
|
VCSSVN_OBJS = vcs-svn/line_buffer.o vcs-svn/repo_tree.o \
|
||||||
vcs-svn/repo_tree.o vcs-svn/fast_export.o vcs-svn/svndump.o
|
vcs-svn/fast_export.o vcs-svn/svndump.o
|
||||||
VCSSVN_TEST_OBJS = test-obj-pool.o test-string-pool.o \
|
VCSSVN_TEST_OBJS = test-line-buffer.o
|
||||||
test-line-buffer.o test-treap.o
|
|
||||||
OBJECTS := $(GIT_OBJS) $(XDIFF_OBJS) $(VCSSVN_OBJS)
|
OBJECTS := $(GIT_OBJS) $(XDIFF_OBJS) $(VCSSVN_OBJS)
|
||||||
|
|
||||||
dep_files := $(foreach f,$(OBJECTS),$(dir $f).depend/$(notdir $f).d)
|
dep_files := $(foreach f,$(OBJECTS),$(dir $f).depend/$(notdir $f).d)
|
||||||
@ -1964,7 +1960,6 @@ xdiff-interface.o $(XDIFF_OBJS): \
|
|||||||
xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h
|
xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h
|
||||||
|
|
||||||
$(VCSSVN_OBJS) $(VCSSVN_TEST_OBJS): $(LIB_H) \
|
$(VCSSVN_OBJS) $(VCSSVN_TEST_OBJS): $(LIB_H) \
|
||||||
vcs-svn/obj_pool.h vcs-svn/trp.h vcs-svn/string_pool.h \
|
|
||||||
vcs-svn/line_buffer.h vcs-svn/repo_tree.h vcs-svn/fast_export.h \
|
vcs-svn/line_buffer.h vcs-svn/repo_tree.h vcs-svn/fast_export.h \
|
||||||
vcs-svn/svndump.h
|
vcs-svn/svndump.h
|
||||||
|
|
||||||
@ -2148,8 +2143,6 @@ test-line-buffer$X: vcs-svn/lib.a
|
|||||||
|
|
||||||
test-parse-options$X: parse-options.o
|
test-parse-options$X: parse-options.o
|
||||||
|
|
||||||
test-string-pool$X: vcs-svn/lib.a
|
|
||||||
|
|
||||||
test-svn-fe$X: vcs-svn/lib.a
|
test-svn-fe$X: vcs-svn/lib.a
|
||||||
|
|
||||||
.PRECIOUS: $(TEST_OBJS)
|
.PRECIOUS: $(TEST_OBJS)
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
test_description='check infrastructure for svn importer'
|
|
||||||
|
|
||||||
. ./test-lib.sh
|
|
||||||
uint32_max=4294967295
|
|
||||||
|
|
||||||
test_expect_success 'obj pool: store data' '
|
|
||||||
cat <<-\EOF >expected &&
|
|
||||||
0
|
|
||||||
1
|
|
||||||
EOF
|
|
||||||
|
|
||||||
test-obj-pool <<-\EOF >actual &&
|
|
||||||
alloc one 16
|
|
||||||
set one 13
|
|
||||||
test one 13
|
|
||||||
reset one
|
|
||||||
EOF
|
|
||||||
test_cmp expected actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success 'obj pool: NULL is offset ~0' '
|
|
||||||
echo "$uint32_max" >expected &&
|
|
||||||
echo null one | test-obj-pool >actual &&
|
|
||||||
test_cmp expected actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success 'obj pool: out-of-bounds access' '
|
|
||||||
cat <<-EOF >expected &&
|
|
||||||
0
|
|
||||||
0
|
|
||||||
$uint32_max
|
|
||||||
$uint32_max
|
|
||||||
16
|
|
||||||
20
|
|
||||||
$uint32_max
|
|
||||||
EOF
|
|
||||||
|
|
||||||
test-obj-pool <<-\EOF >actual &&
|
|
||||||
alloc one 16
|
|
||||||
alloc two 16
|
|
||||||
offset one 20
|
|
||||||
offset two 20
|
|
||||||
alloc one 5
|
|
||||||
offset one 20
|
|
||||||
free one 1
|
|
||||||
offset one 20
|
|
||||||
reset one
|
|
||||||
reset two
|
|
||||||
EOF
|
|
||||||
test_cmp expected actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success 'obj pool: high-water mark' '
|
|
||||||
cat <<-\EOF >expected &&
|
|
||||||
0
|
|
||||||
0
|
|
||||||
10
|
|
||||||
20
|
|
||||||
20
|
|
||||||
20
|
|
||||||
EOF
|
|
||||||
|
|
||||||
test-obj-pool <<-\EOF >actual &&
|
|
||||||
alloc one 10
|
|
||||||
committed one
|
|
||||||
alloc one 10
|
|
||||||
commit one
|
|
||||||
committed one
|
|
||||||
alloc one 10
|
|
||||||
free one 20
|
|
||||||
committed one
|
|
||||||
reset one
|
|
||||||
EOF
|
|
||||||
test_cmp expected actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success 'string pool' '
|
|
||||||
echo a does not equal b >expected.differ &&
|
|
||||||
echo a equals a >expected.match &&
|
|
||||||
echo equals equals equals >expected.matchmore &&
|
|
||||||
|
|
||||||
test-string-pool "a,--b" >actual.differ &&
|
|
||||||
test-string-pool "a,a" >actual.match &&
|
|
||||||
test-string-pool "equals-equals" >actual.matchmore &&
|
|
||||||
test_must_fail test-string-pool a,a,a &&
|
|
||||||
test_must_fail test-string-pool a &&
|
|
||||||
|
|
||||||
test_cmp expected.differ actual.differ &&
|
|
||||||
test_cmp expected.match actual.match &&
|
|
||||||
test_cmp expected.matchmore actual.matchmore
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success 'treap sort' '
|
|
||||||
cat <<-\EOF >unsorted &&
|
|
||||||
68
|
|
||||||
12
|
|
||||||
13
|
|
||||||
13
|
|
||||||
68
|
|
||||||
13
|
|
||||||
13
|
|
||||||
21
|
|
||||||
10
|
|
||||||
11
|
|
||||||
12
|
|
||||||
13
|
|
||||||
13
|
|
||||||
EOF
|
|
||||||
sort unsorted >expected &&
|
|
||||||
|
|
||||||
test-treap <unsorted >actual &&
|
|
||||||
test_cmp expected actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test_done
|
|
116
test-obj-pool.c
116
test-obj-pool.c
@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* test-obj-pool.c: code to exercise the svn importer's object pool
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "cache.h"
|
|
||||||
#include "vcs-svn/obj_pool.h"
|
|
||||||
|
|
||||||
enum pool { POOL_ONE, POOL_TWO };
|
|
||||||
obj_pool_gen(one, int, 1)
|
|
||||||
obj_pool_gen(two, int, 4096)
|
|
||||||
|
|
||||||
static uint32_t strtouint32(const char *s)
|
|
||||||
{
|
|
||||||
char *end;
|
|
||||||
uintmax_t n = strtoumax(s, &end, 10);
|
|
||||||
if (*s == '\0' || (*end != '\n' && *end != '\0'))
|
|
||||||
die("invalid offset: %s", s);
|
|
||||||
return (uint32_t) n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_command(const char *command, enum pool pool, const char *arg)
|
|
||||||
{
|
|
||||||
switch (*command) {
|
|
||||||
case 'a':
|
|
||||||
if (!prefixcmp(command, "alloc ")) {
|
|
||||||
uint32_t n = strtouint32(arg);
|
|
||||||
printf("%"PRIu32"\n",
|
|
||||||
pool == POOL_ONE ?
|
|
||||||
one_alloc(n) : two_alloc(n));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case 'c':
|
|
||||||
if (!prefixcmp(command, "commit ")) {
|
|
||||||
pool == POOL_ONE ? one_commit() : two_commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!prefixcmp(command, "committed ")) {
|
|
||||||
printf("%"PRIu32"\n",
|
|
||||||
pool == POOL_ONE ?
|
|
||||||
one_pool.committed : two_pool.committed);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case 'f':
|
|
||||||
if (!prefixcmp(command, "free ")) {
|
|
||||||
uint32_t n = strtouint32(arg);
|
|
||||||
pool == POOL_ONE ? one_free(n) : two_free(n);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case 'n':
|
|
||||||
if (!prefixcmp(command, "null ")) {
|
|
||||||
printf("%"PRIu32"\n",
|
|
||||||
pool == POOL_ONE ?
|
|
||||||
one_offset(NULL) : two_offset(NULL));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case 'o':
|
|
||||||
if (!prefixcmp(command, "offset ")) {
|
|
||||||
uint32_t n = strtouint32(arg);
|
|
||||||
printf("%"PRIu32"\n",
|
|
||||||
pool == POOL_ONE ?
|
|
||||||
one_offset(one_pointer(n)) :
|
|
||||||
two_offset(two_pointer(n)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case 'r':
|
|
||||||
if (!prefixcmp(command, "reset ")) {
|
|
||||||
pool == POOL_ONE ? one_reset() : two_reset();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case 's':
|
|
||||||
if (!prefixcmp(command, "set ")) {
|
|
||||||
uint32_t n = strtouint32(arg);
|
|
||||||
if (pool == POOL_ONE)
|
|
||||||
*one_pointer(n) = 1;
|
|
||||||
else
|
|
||||||
*two_pointer(n) = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case 't':
|
|
||||||
if (!prefixcmp(command, "test ")) {
|
|
||||||
uint32_t n = strtouint32(arg);
|
|
||||||
printf("%d\n", pool == POOL_ONE ?
|
|
||||||
*one_pointer(n) : *two_pointer(n));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
die("unrecognized command: %s", command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_line(const char *line)
|
|
||||||
{
|
|
||||||
const char *arg = strchr(line, ' ');
|
|
||||||
enum pool pool;
|
|
||||||
|
|
||||||
if (arg && !prefixcmp(arg + 1, "one"))
|
|
||||||
pool = POOL_ONE;
|
|
||||||
else if (arg && !prefixcmp(arg + 1, "two"))
|
|
||||||
pool = POOL_TWO;
|
|
||||||
else
|
|
||||||
die("no pool specified: %s", line);
|
|
||||||
|
|
||||||
handle_command(line, pool, arg + strlen("one "));
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
struct strbuf sb = STRBUF_INIT;
|
|
||||||
if (argc != 1)
|
|
||||||
usage("test-obj-str < script");
|
|
||||||
|
|
||||||
while (strbuf_getline(&sb, stdin, '\n') != EOF)
|
|
||||||
handle_line(sb.buf);
|
|
||||||
strbuf_release(&sb);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* test-string-pool.c: code to exercise the svn importer's string pool
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "git-compat-util.h"
|
|
||||||
#include "vcs-svn/string_pool.h"
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
const uint32_t unequal = pool_intern("does not equal");
|
|
||||||
const uint32_t equal = pool_intern("equals");
|
|
||||||
uint32_t buf[3];
|
|
||||||
uint32_t n;
|
|
||||||
|
|
||||||
if (argc != 2)
|
|
||||||
usage("test-string-pool <string>,<string>");
|
|
||||||
|
|
||||||
n = pool_tok_seq(3, buf, ",-", argv[1]);
|
|
||||||
if (n >= 3)
|
|
||||||
die("too many strings");
|
|
||||||
if (n <= 1)
|
|
||||||
die("too few strings");
|
|
||||||
|
|
||||||
buf[2] = buf[1];
|
|
||||||
buf[1] = (buf[0] == buf[2]) ? equal : unequal;
|
|
||||||
pool_print_seq(3, buf, ' ', stdout);
|
|
||||||
fputc('\n', stdout);
|
|
||||||
|
|
||||||
pool_reset();
|
|
||||||
return 0;
|
|
||||||
}
|
|
70
test-treap.c
70
test-treap.c
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* test-treap.c: code to exercise the svn importer's treap structure
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "cache.h"
|
|
||||||
#include "vcs-svn/obj_pool.h"
|
|
||||||
#include "vcs-svn/trp.h"
|
|
||||||
|
|
||||||
struct int_node {
|
|
||||||
uintmax_t n;
|
|
||||||
struct trp_node children;
|
|
||||||
};
|
|
||||||
|
|
||||||
obj_pool_gen(node, struct int_node, 3)
|
|
||||||
|
|
||||||
static int node_cmp(struct int_node *a, struct int_node *b)
|
|
||||||
{
|
|
||||||
return (a->n > b->n) - (a->n < b->n);
|
|
||||||
}
|
|
||||||
|
|
||||||
trp_gen(static, treap_, struct int_node, children, node, node_cmp)
|
|
||||||
|
|
||||||
static void strtonode(struct int_node *item, const char *s)
|
|
||||||
{
|
|
||||||
char *end;
|
|
||||||
item->n = strtoumax(s, &end, 10);
|
|
||||||
if (*s == '\0' || (*end != '\n' && *end != '\0'))
|
|
||||||
die("invalid integer: %s", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
struct strbuf sb = STRBUF_INIT;
|
|
||||||
struct trp_root root = { ~0 };
|
|
||||||
uint32_t item;
|
|
||||||
|
|
||||||
if (argc != 1)
|
|
||||||
usage("test-treap < ints");
|
|
||||||
|
|
||||||
while (strbuf_getline(&sb, stdin, '\n') != EOF) {
|
|
||||||
struct int_node *node = node_pointer(node_alloc(1));
|
|
||||||
|
|
||||||
item = node_offset(node);
|
|
||||||
strtonode(node, sb.buf);
|
|
||||||
node = treap_insert(&root, node_pointer(item));
|
|
||||||
if (node_offset(node) != item)
|
|
||||||
die("inserted %"PRIu32" in place of %"PRIu32"",
|
|
||||||
node_offset(node), item);
|
|
||||||
}
|
|
||||||
|
|
||||||
item = node_offset(treap_first(&root));
|
|
||||||
while (~item) {
|
|
||||||
uint32_t next;
|
|
||||||
struct int_node *tmp = node_pointer(node_alloc(1));
|
|
||||||
|
|
||||||
tmp->n = node_pointer(item)->n;
|
|
||||||
next = node_offset(treap_next(&root, node_pointer(item)));
|
|
||||||
|
|
||||||
treap_remove(&root, node_pointer(item));
|
|
||||||
item = node_offset(treap_nsearch(&root, tmp));
|
|
||||||
|
|
||||||
if (item != next && (!~item || node_pointer(item)->n != tmp->n))
|
|
||||||
die("found %"PRIuMAX" in place of %"PRIuMAX"",
|
|
||||||
~item ? node_pointer(item)->n : ~(uintmax_t) 0,
|
|
||||||
~next ? node_pointer(next)->n : ~(uintmax_t) 0);
|
|
||||||
printf("%"PRIuMAX"\n", tmp->n);
|
|
||||||
}
|
|
||||||
node_reset();
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,9 +1,6 @@
|
|||||||
Copyright (C) 2010 David Barr <david.barr@cordelta.com>.
|
Copyright (C) 2010 David Barr <david.barr@cordelta.com>.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Copyright (C) 2008 Jason Evans <jasone@canonware.com>.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Copyright (C) 2005 Stefan Hegny, hydrografix Consulting GmbH,
|
Copyright (C) 2005 Stefan Hegny, hydrografix Consulting GmbH,
|
||||||
Frankfurt/Main, Germany
|
Frankfurt/Main, Germany
|
||||||
and others, see http://svn2cc.sarovar.org
|
and others, see http://svn2cc.sarovar.org
|
||||||
|
@ -4,10 +4,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "git-compat-util.h"
|
#include "git-compat-util.h"
|
||||||
|
#include "strbuf.h"
|
||||||
|
#include "quote.h"
|
||||||
#include "fast_export.h"
|
#include "fast_export.h"
|
||||||
#include "line_buffer.h"
|
#include "line_buffer.h"
|
||||||
#include "repo_tree.h"
|
#include "repo_tree.h"
|
||||||
#include "string_pool.h"
|
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
|
|
||||||
#define MAX_GITSVN_LINE_LEN 4096
|
#define MAX_GITSVN_LINE_LEN 4096
|
||||||
@ -32,30 +33,30 @@ void fast_export_reset(void)
|
|||||||
buffer_reset(&report_buffer);
|
buffer_reset(&report_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fast_export_delete(uint32_t depth, const uint32_t *path)
|
void fast_export_delete(const char *path)
|
||||||
{
|
{
|
||||||
printf("D \"");
|
putchar('D');
|
||||||
pool_print_seq_q(depth, path, '/', stdout);
|
putchar(' ');
|
||||||
printf("\"\n");
|
quote_c_style(path, NULL, stdout, 0);
|
||||||
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fast_export_truncate(uint32_t depth, const uint32_t *path, uint32_t mode)
|
static void fast_export_truncate(const char *path, uint32_t mode)
|
||||||
{
|
{
|
||||||
fast_export_modify(depth, path, mode, "inline");
|
fast_export_modify(path, mode, "inline");
|
||||||
printf("data 0\n\n");
|
printf("data 0\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void fast_export_modify(uint32_t depth, const uint32_t *path, uint32_t mode,
|
void fast_export_modify(const char *path, uint32_t mode, const char *dataref)
|
||||||
const char *dataref)
|
|
||||||
{
|
{
|
||||||
/* Mode must be 100644, 100755, 120000, or 160000. */
|
/* Mode must be 100644, 100755, 120000, or 160000. */
|
||||||
if (!dataref) {
|
if (!dataref) {
|
||||||
fast_export_truncate(depth, path, mode);
|
fast_export_truncate(path, mode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf("M %06"PRIo32" %s \"", mode, dataref);
|
printf("M %06"PRIo32" %s ", mode, dataref);
|
||||||
pool_print_seq_q(depth, path, '/', stdout);
|
quote_c_style(path, NULL, stdout, 0);
|
||||||
printf("\"\n");
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
static char gitsvnline[MAX_GITSVN_LINE_LEN];
|
static char gitsvnline[MAX_GITSVN_LINE_LEN];
|
||||||
@ -96,20 +97,20 @@ void fast_export_end_commit(uint32_t revision)
|
|||||||
printf("progress Imported commit %"PRIu32".\n\n", revision);
|
printf("progress Imported commit %"PRIu32".\n\n", revision);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ls_from_rev(uint32_t rev, uint32_t depth, const uint32_t *path)
|
static void ls_from_rev(uint32_t rev, const char *path)
|
||||||
{
|
{
|
||||||
/* ls :5 path/to/old/file */
|
/* ls :5 path/to/old/file */
|
||||||
printf("ls :%"PRIu32" \"", rev);
|
printf("ls :%"PRIu32" ", rev);
|
||||||
pool_print_seq_q(depth, path, '/', stdout);
|
quote_c_style(path, NULL, stdout, 0);
|
||||||
printf("\"\n");
|
putchar('\n');
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ls_from_active_commit(uint32_t depth, const uint32_t *path)
|
static void ls_from_active_commit(const char *path)
|
||||||
{
|
{
|
||||||
/* ls "path/to/file" */
|
/* ls "path/to/file" */
|
||||||
printf("ls \"");
|
printf("ls \"");
|
||||||
pool_print_seq_q(depth, path, '/', stdout);
|
quote_c_style(path, NULL, stdout, 1);
|
||||||
printf("\"\n");
|
printf("\"\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
@ -186,16 +187,15 @@ static int parse_ls_response(const char *response, uint32_t *mode,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fast_export_ls_rev(uint32_t rev, uint32_t depth, const uint32_t *path,
|
int fast_export_ls_rev(uint32_t rev, const char *path,
|
||||||
uint32_t *mode, struct strbuf *dataref)
|
uint32_t *mode, struct strbuf *dataref)
|
||||||
{
|
{
|
||||||
ls_from_rev(rev, depth, path);
|
ls_from_rev(rev, path);
|
||||||
return parse_ls_response(get_response_line(), mode, dataref);
|
return parse_ls_response(get_response_line(), mode, dataref);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fast_export_ls(uint32_t depth, const uint32_t *path,
|
int fast_export_ls(const char *path, uint32_t *mode, struct strbuf *dataref)
|
||||||
uint32_t *mode, struct strbuf *dataref)
|
|
||||||
{
|
{
|
||||||
ls_from_active_commit(depth, path);
|
ls_from_active_commit(path);
|
||||||
return parse_ls_response(get_response_line(), mode, dataref);
|
return parse_ls_response(get_response_line(), mode, dataref);
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,8 @@ void fast_export_init(int fd);
|
|||||||
void fast_export_deinit(void);
|
void fast_export_deinit(void);
|
||||||
void fast_export_reset(void);
|
void fast_export_reset(void);
|
||||||
|
|
||||||
void fast_export_delete(uint32_t depth, const uint32_t *path);
|
void fast_export_delete(const char *path);
|
||||||
void fast_export_modify(uint32_t depth, const uint32_t *path,
|
void fast_export_modify(const char *path, uint32_t mode, const char *dataref);
|
||||||
uint32_t mode, const char *dataref);
|
|
||||||
void fast_export_begin_commit(uint32_t revision, const char *author,
|
void fast_export_begin_commit(uint32_t revision, const char *author,
|
||||||
const struct strbuf *log, const char *uuid,
|
const struct strbuf *log, const char *uuid,
|
||||||
const char *url, unsigned long timestamp);
|
const char *url, unsigned long timestamp);
|
||||||
@ -18,9 +17,9 @@ void fast_export_end_commit(uint32_t revision);
|
|||||||
void fast_export_data(uint32_t mode, uint32_t len, struct line_buffer *input);
|
void fast_export_data(uint32_t mode, uint32_t len, struct line_buffer *input);
|
||||||
|
|
||||||
/* If there is no such file at that rev, returns -1, errno == ENOENT. */
|
/* If there is no such file at that rev, returns -1, errno == ENOENT. */
|
||||||
int fast_export_ls_rev(uint32_t rev, uint32_t depth, const uint32_t *path,
|
int fast_export_ls_rev(uint32_t rev, const char *path,
|
||||||
uint32_t *mode_out, struct strbuf *dataref_out);
|
uint32_t *mode_out, struct strbuf *dataref_out);
|
||||||
int fast_export_ls(uint32_t depth, const uint32_t *path,
|
int fast_export_ls(const char *path,
|
||||||
uint32_t *mode_out, struct strbuf *dataref_out);
|
uint32_t *mode_out, struct strbuf *dataref_out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under a two-clause BSD-style license.
|
|
||||||
* See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef OBJ_POOL_H_
|
|
||||||
#define OBJ_POOL_H_
|
|
||||||
|
|
||||||
#include "git-compat-util.h"
|
|
||||||
|
|
||||||
#define MAYBE_UNUSED __attribute__((__unused__))
|
|
||||||
|
|
||||||
#define obj_pool_gen(pre, obj_t, initial_capacity) \
|
|
||||||
static struct { \
|
|
||||||
uint32_t committed; \
|
|
||||||
uint32_t size; \
|
|
||||||
uint32_t capacity; \
|
|
||||||
obj_t *base; \
|
|
||||||
} pre##_pool = {0, 0, 0, NULL}; \
|
|
||||||
static MAYBE_UNUSED uint32_t pre##_alloc(uint32_t count) \
|
|
||||||
{ \
|
|
||||||
uint32_t offset; \
|
|
||||||
if (pre##_pool.size + count > pre##_pool.capacity) { \
|
|
||||||
while (pre##_pool.size + count > pre##_pool.capacity) \
|
|
||||||
if (pre##_pool.capacity) \
|
|
||||||
pre##_pool.capacity *= 2; \
|
|
||||||
else \
|
|
||||||
pre##_pool.capacity = initial_capacity; \
|
|
||||||
pre##_pool.base = realloc(pre##_pool.base, \
|
|
||||||
pre##_pool.capacity * sizeof(obj_t)); \
|
|
||||||
} \
|
|
||||||
offset = pre##_pool.size; \
|
|
||||||
pre##_pool.size += count; \
|
|
||||||
return offset; \
|
|
||||||
} \
|
|
||||||
static MAYBE_UNUSED void pre##_free(uint32_t count) \
|
|
||||||
{ \
|
|
||||||
pre##_pool.size -= count; \
|
|
||||||
} \
|
|
||||||
static MAYBE_UNUSED uint32_t pre##_offset(obj_t *obj) \
|
|
||||||
{ \
|
|
||||||
return obj == NULL ? ~0 : obj - pre##_pool.base; \
|
|
||||||
} \
|
|
||||||
static MAYBE_UNUSED obj_t *pre##_pointer(uint32_t offset) \
|
|
||||||
{ \
|
|
||||||
return offset >= pre##_pool.size ? NULL : &pre##_pool.base[offset]; \
|
|
||||||
} \
|
|
||||||
static MAYBE_UNUSED void pre##_commit(void) \
|
|
||||||
{ \
|
|
||||||
pre##_pool.committed = pre##_pool.size; \
|
|
||||||
} \
|
|
||||||
static MAYBE_UNUSED void pre##_reset(void) \
|
|
||||||
{ \
|
|
||||||
free(pre##_pool.base); \
|
|
||||||
pre##_pool.base = NULL; \
|
|
||||||
pre##_pool.size = 0; \
|
|
||||||
pre##_pool.capacity = 0; \
|
|
||||||
pre##_pool.committed = 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -8,13 +8,13 @@
|
|||||||
#include "repo_tree.h"
|
#include "repo_tree.h"
|
||||||
#include "fast_export.h"
|
#include "fast_export.h"
|
||||||
|
|
||||||
const char *repo_read_path(const uint32_t *path, uint32_t *mode_out)
|
const char *repo_read_path(const char *path, uint32_t *mode_out)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
static struct strbuf buf = STRBUF_INIT;
|
static struct strbuf buf = STRBUF_INIT;
|
||||||
|
|
||||||
strbuf_reset(&buf);
|
strbuf_reset(&buf);
|
||||||
err = fast_export_ls(REPO_MAX_PATH_DEPTH, path, mode_out, &buf);
|
err = fast_export_ls(path, mode_out, &buf);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
die_errno("BUG: unexpected fast_export_ls error");
|
die_errno("BUG: unexpected fast_export_ls error");
|
||||||
@ -25,24 +25,24 @@ const char *repo_read_path(const uint32_t *path, uint32_t *mode_out)
|
|||||||
return buf.buf;
|
return buf.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void repo_copy(uint32_t revision, const uint32_t *src, const uint32_t *dst)
|
void repo_copy(uint32_t revision, const char *src, const char *dst)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
uint32_t mode;
|
uint32_t mode;
|
||||||
static struct strbuf data = STRBUF_INIT;
|
static struct strbuf data = STRBUF_INIT;
|
||||||
|
|
||||||
strbuf_reset(&data);
|
strbuf_reset(&data);
|
||||||
err = fast_export_ls_rev(revision, REPO_MAX_PATH_DEPTH, src, &mode, &data);
|
err = fast_export_ls_rev(revision, src, &mode, &data);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
die_errno("BUG: unexpected fast_export_ls_rev error");
|
die_errno("BUG: unexpected fast_export_ls_rev error");
|
||||||
fast_export_delete(REPO_MAX_PATH_DEPTH, dst);
|
fast_export_delete(dst);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fast_export_modify(REPO_MAX_PATH_DEPTH, dst, mode, data.buf);
|
fast_export_modify(dst, mode, data.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void repo_delete(uint32_t *path)
|
void repo_delete(const char *path)
|
||||||
{
|
{
|
||||||
fast_export_delete(REPO_MAX_PATH_DEPTH, path);
|
fast_export_delete(path);
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,11 @@ struct strbuf;
|
|||||||
#define REPO_MODE_EXE 0100755
|
#define REPO_MODE_EXE 0100755
|
||||||
#define REPO_MODE_LNK 0120000
|
#define REPO_MODE_LNK 0120000
|
||||||
|
|
||||||
#define REPO_MAX_PATH_LEN 4096
|
|
||||||
#define REPO_MAX_PATH_DEPTH 1000
|
|
||||||
|
|
||||||
uint32_t next_blob_mark(void);
|
uint32_t next_blob_mark(void);
|
||||||
void repo_copy(uint32_t revision, const uint32_t *src, const uint32_t *dst);
|
void repo_copy(uint32_t revision, const char *src, const char *dst);
|
||||||
void repo_add(uint32_t *path, uint32_t mode, uint32_t blob_mark);
|
void repo_add(const char *path, uint32_t mode, uint32_t blob_mark);
|
||||||
const char *repo_read_path(const uint32_t *path, uint32_t *mode_out);
|
const char *repo_read_path(const char *path, uint32_t *mode_out);
|
||||||
void repo_delete(uint32_t *path);
|
void repo_delete(const char *path);
|
||||||
void repo_commit(uint32_t revision, const char *author,
|
void repo_commit(uint32_t revision, const char *author,
|
||||||
const struct strbuf *log, const char *uuid, const char *url,
|
const struct strbuf *log, const char *uuid, const char *url,
|
||||||
long unsigned timestamp);
|
long unsigned timestamp);
|
||||||
|
@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under a two-clause BSD-style license.
|
|
||||||
* See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "git-compat-util.h"
|
|
||||||
#include "quote.h"
|
|
||||||
#include "trp.h"
|
|
||||||
#include "obj_pool.h"
|
|
||||||
#include "string_pool.h"
|
|
||||||
|
|
||||||
static struct trp_root tree = { ~0 };
|
|
||||||
|
|
||||||
struct node {
|
|
||||||
uint32_t offset;
|
|
||||||
struct trp_node children;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Two memory pools: one for struct node, and another for strings */
|
|
||||||
obj_pool_gen(node, struct node, 4096)
|
|
||||||
obj_pool_gen(string, char, 4096)
|
|
||||||
|
|
||||||
static char *node_value(struct node *node)
|
|
||||||
{
|
|
||||||
return node ? string_pointer(node->offset) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int node_cmp(struct node *a, struct node *b)
|
|
||||||
{
|
|
||||||
return strcmp(node_value(a), node_value(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build a Treap from the node structure (a trp_node w/ offset) */
|
|
||||||
trp_gen(static, tree_, struct node, children, node, node_cmp)
|
|
||||||
|
|
||||||
const char *pool_fetch(uint32_t entry)
|
|
||||||
{
|
|
||||||
return node_value(node_pointer(entry));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t pool_intern(const char *key)
|
|
||||||
{
|
|
||||||
/* Canonicalize key */
|
|
||||||
struct node *match = NULL, *node;
|
|
||||||
uint32_t key_len;
|
|
||||||
if (key == NULL)
|
|
||||||
return ~0;
|
|
||||||
key_len = strlen(key) + 1;
|
|
||||||
node = node_pointer(node_alloc(1));
|
|
||||||
node->offset = string_alloc(key_len);
|
|
||||||
strcpy(node_value(node), key);
|
|
||||||
match = tree_search(&tree, node);
|
|
||||||
if (!match) {
|
|
||||||
tree_insert(&tree, node);
|
|
||||||
} else {
|
|
||||||
node_free(1);
|
|
||||||
string_free(key_len);
|
|
||||||
node = match;
|
|
||||||
}
|
|
||||||
return node_offset(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t pool_tok_r(char *str, const char *delim, char **saveptr)
|
|
||||||
{
|
|
||||||
char *token = strtok_r(str, delim, saveptr);
|
|
||||||
return token ? pool_intern(token) : ~0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pool_print_seq(uint32_t len, const uint32_t *seq, char delim, FILE *stream)
|
|
||||||
{
|
|
||||||
uint32_t i;
|
|
||||||
for (i = 0; i < len && ~seq[i]; i++) {
|
|
||||||
fputs(pool_fetch(seq[i]), stream);
|
|
||||||
if (i < len - 1 && ~seq[i + 1])
|
|
||||||
fputc(delim, stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void pool_print_seq_q(uint32_t len, const uint32_t *seq, char delim, FILE *stream)
|
|
||||||
{
|
|
||||||
uint32_t i;
|
|
||||||
for (i = 0; i < len && ~seq[i]; i++) {
|
|
||||||
quote_c_style(pool_fetch(seq[i]), NULL, stream, 1);
|
|
||||||
if (i < len - 1 && ~seq[i + 1])
|
|
||||||
fputc(delim, stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t pool_tok_seq(uint32_t sz, uint32_t *seq, const char *delim, char *str)
|
|
||||||
{
|
|
||||||
char *context = NULL;
|
|
||||||
uint32_t token = ~0;
|
|
||||||
uint32_t length;
|
|
||||||
|
|
||||||
if (sz == 0)
|
|
||||||
return ~0;
|
|
||||||
if (str)
|
|
||||||
token = pool_tok_r(str, delim, &context);
|
|
||||||
for (length = 0; length < sz; length++) {
|
|
||||||
seq[length] = token;
|
|
||||||
if (token == ~0)
|
|
||||||
return length;
|
|
||||||
token = pool_tok_r(NULL, delim, &context);
|
|
||||||
}
|
|
||||||
seq[sz - 1] = ~0;
|
|
||||||
return sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pool_reset(void)
|
|
||||||
{
|
|
||||||
node_reset();
|
|
||||||
string_reset();
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#ifndef STRING_POOL_H_
|
|
||||||
#define STRING_POOL_H_
|
|
||||||
|
|
||||||
uint32_t pool_intern(const char *key);
|
|
||||||
const char *pool_fetch(uint32_t entry);
|
|
||||||
uint32_t pool_tok_r(char *str, const char *delim, char **saveptr);
|
|
||||||
void pool_print_seq(uint32_t len, const uint32_t *seq, char delim, FILE *stream);
|
|
||||||
void pool_print_seq_q(uint32_t len, const uint32_t *seq, char delim, FILE *stream);
|
|
||||||
uint32_t pool_tok_seq(uint32_t sz, uint32_t *seq, const char *delim, char *str);
|
|
||||||
void pool_reset(void);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,43 +0,0 @@
|
|||||||
string_pool API
|
|
||||||
===============
|
|
||||||
|
|
||||||
The string_pool API provides facilities for replacing strings
|
|
||||||
with integer keys that can be more easily compared and stored.
|
|
||||||
The facilities are designed so that one could teach Git without
|
|
||||||
too much trouble to store the information needed for these keys to
|
|
||||||
remain valid over multiple executions.
|
|
||||||
|
|
||||||
Functions
|
|
||||||
---------
|
|
||||||
|
|
||||||
pool_intern::
|
|
||||||
Include a string in the string pool and get its key.
|
|
||||||
If that string is already in the pool, retrieves its
|
|
||||||
existing key.
|
|
||||||
|
|
||||||
pool_fetch::
|
|
||||||
Retrieve the string associated to a given key.
|
|
||||||
|
|
||||||
pool_tok_r::
|
|
||||||
Extract the key of the next token from a string.
|
|
||||||
Interface mimics strtok_r.
|
|
||||||
|
|
||||||
pool_print_seq::
|
|
||||||
Print a sequence of strings named by key to a file, using the
|
|
||||||
specified delimiter to separate them.
|
|
||||||
|
|
||||||
If NULL (key ~0) appears in the sequence, the sequence ends
|
|
||||||
early.
|
|
||||||
|
|
||||||
pool_tok_seq::
|
|
||||||
Split a string into tokens, storing the keys of segments
|
|
||||||
into a caller-provided array.
|
|
||||||
|
|
||||||
Unless sz is 0, the array will always be ~0-terminated.
|
|
||||||
If there is not enough room for all the tokens, the
|
|
||||||
array holds as many tokens as fit in the entries before
|
|
||||||
the terminating ~0. Return value is the index after the
|
|
||||||
last token, or sz if the tokens did not fit.
|
|
||||||
|
|
||||||
pool_reset::
|
|
||||||
Deallocate storage for the string pool.
|
|
@ -11,7 +11,6 @@
|
|||||||
#include "repo_tree.h"
|
#include "repo_tree.h"
|
||||||
#include "fast_export.h"
|
#include "fast_export.h"
|
||||||
#include "line_buffer.h"
|
#include "line_buffer.h"
|
||||||
#include "string_pool.h"
|
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -41,7 +40,7 @@ static struct line_buffer input = LINE_BUFFER_INIT;
|
|||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
uint32_t action, propLength, textLength, srcRev, type;
|
uint32_t action, propLength, textLength, srcRev, type;
|
||||||
uint32_t src[REPO_MAX_PATH_DEPTH], dst[REPO_MAX_PATH_DEPTH];
|
struct strbuf src, dst;
|
||||||
uint32_t text_delta, prop_delta;
|
uint32_t text_delta, prop_delta;
|
||||||
} node_ctx;
|
} node_ctx;
|
||||||
|
|
||||||
@ -62,9 +61,11 @@ static void reset_node_ctx(char *fname)
|
|||||||
node_ctx.action = NODEACT_UNKNOWN;
|
node_ctx.action = NODEACT_UNKNOWN;
|
||||||
node_ctx.propLength = LENGTH_UNKNOWN;
|
node_ctx.propLength = LENGTH_UNKNOWN;
|
||||||
node_ctx.textLength = LENGTH_UNKNOWN;
|
node_ctx.textLength = LENGTH_UNKNOWN;
|
||||||
node_ctx.src[0] = ~0;
|
strbuf_reset(&node_ctx.src);
|
||||||
node_ctx.srcRev = 0;
|
node_ctx.srcRev = 0;
|
||||||
pool_tok_seq(REPO_MAX_PATH_DEPTH, node_ctx.dst, "/", fname);
|
strbuf_reset(&node_ctx.dst);
|
||||||
|
if (fname)
|
||||||
|
strbuf_addstr(&node_ctx.dst, fname);
|
||||||
node_ctx.text_delta = 0;
|
node_ctx.text_delta = 0;
|
||||||
node_ctx.prop_delta = 0;
|
node_ctx.prop_delta = 0;
|
||||||
}
|
}
|
||||||
@ -224,15 +225,15 @@ static void handle_node(void)
|
|||||||
if (have_text || have_props || node_ctx.srcRev)
|
if (have_text || have_props || node_ctx.srcRev)
|
||||||
die("invalid dump: deletion node has "
|
die("invalid dump: deletion node has "
|
||||||
"copyfrom info, text, or properties");
|
"copyfrom info, text, or properties");
|
||||||
repo_delete(node_ctx.dst);
|
repo_delete(node_ctx.dst.buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (node_ctx.action == NODEACT_REPLACE) {
|
if (node_ctx.action == NODEACT_REPLACE) {
|
||||||
repo_delete(node_ctx.dst);
|
repo_delete(node_ctx.dst.buf);
|
||||||
node_ctx.action = NODEACT_ADD;
|
node_ctx.action = NODEACT_ADD;
|
||||||
}
|
}
|
||||||
if (node_ctx.srcRev) {
|
if (node_ctx.srcRev) {
|
||||||
repo_copy(node_ctx.srcRev, node_ctx.src, node_ctx.dst);
|
repo_copy(node_ctx.srcRev, node_ctx.src.buf, node_ctx.dst.buf);
|
||||||
if (node_ctx.action == NODEACT_ADD)
|
if (node_ctx.action == NODEACT_ADD)
|
||||||
node_ctx.action = NODEACT_CHANGE;
|
node_ctx.action = NODEACT_CHANGE;
|
||||||
}
|
}
|
||||||
@ -242,13 +243,13 @@ static void handle_node(void)
|
|||||||
/*
|
/*
|
||||||
* Find old content (old_data) and decide on the new mode.
|
* Find old content (old_data) and decide on the new mode.
|
||||||
*/
|
*/
|
||||||
if (node_ctx.action == NODEACT_CHANGE && !~*node_ctx.dst) {
|
if (node_ctx.action == NODEACT_CHANGE && !*node_ctx.dst.buf) {
|
||||||
if (type != REPO_MODE_DIR)
|
if (type != REPO_MODE_DIR)
|
||||||
die("invalid dump: root of tree is not a regular file");
|
die("invalid dump: root of tree is not a regular file");
|
||||||
old_data = NULL;
|
old_data = NULL;
|
||||||
} else if (node_ctx.action == NODEACT_CHANGE) {
|
} else if (node_ctx.action == NODEACT_CHANGE) {
|
||||||
uint32_t mode;
|
uint32_t mode;
|
||||||
old_data = repo_read_path(node_ctx.dst, &mode);
|
old_data = repo_read_path(node_ctx.dst.buf, &mode);
|
||||||
if (mode == REPO_MODE_DIR && type != REPO_MODE_DIR)
|
if (mode == REPO_MODE_DIR && type != REPO_MODE_DIR)
|
||||||
die("invalid dump: cannot modify a directory into a file");
|
die("invalid dump: cannot modify a directory into a file");
|
||||||
if (mode != REPO_MODE_DIR && type == REPO_MODE_DIR)
|
if (mode != REPO_MODE_DIR && type == REPO_MODE_DIR)
|
||||||
@ -285,12 +286,10 @@ static void handle_node(void)
|
|||||||
/* For the fast_export_* functions, NULL means empty. */
|
/* For the fast_export_* functions, NULL means empty. */
|
||||||
old_data = NULL;
|
old_data = NULL;
|
||||||
if (!have_text) {
|
if (!have_text) {
|
||||||
fast_export_modify(REPO_MAX_PATH_DEPTH, node_ctx.dst,
|
fast_export_modify(node_ctx.dst.buf, node_ctx.type, old_data);
|
||||||
node_ctx.type, old_data);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fast_export_modify(REPO_MAX_PATH_DEPTH, node_ctx.dst,
|
fast_export_modify(node_ctx.dst.buf, node_ctx.type, "inline");
|
||||||
node_ctx.type, "inline");
|
|
||||||
fast_export_data(node_ctx.type, node_ctx.textLength, &input);
|
fast_export_data(node_ctx.type, node_ctx.textLength, &input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +393,8 @@ void svndump_read(const char *url)
|
|||||||
case sizeof("Node-copyfrom-path"):
|
case sizeof("Node-copyfrom-path"):
|
||||||
if (constcmp(t, "Node-copyfrom-path"))
|
if (constcmp(t, "Node-copyfrom-path"))
|
||||||
continue;
|
continue;
|
||||||
pool_tok_seq(REPO_MAX_PATH_DEPTH, node_ctx.src, "/", val);
|
strbuf_reset(&node_ctx.src);
|
||||||
|
strbuf_addstr(&node_ctx.src, val);
|
||||||
break;
|
break;
|
||||||
case sizeof("Node-copyfrom-rev"):
|
case sizeof("Node-copyfrom-rev"):
|
||||||
if (constcmp(t, "Node-copyfrom-rev"))
|
if (constcmp(t, "Node-copyfrom-rev"))
|
||||||
@ -459,6 +459,8 @@ int svndump_init(const char *filename)
|
|||||||
strbuf_init(&dump_ctx.url, 4096);
|
strbuf_init(&dump_ctx.url, 4096);
|
||||||
strbuf_init(&rev_ctx.log, 4096);
|
strbuf_init(&rev_ctx.log, 4096);
|
||||||
strbuf_init(&rev_ctx.author, 4096);
|
strbuf_init(&rev_ctx.author, 4096);
|
||||||
|
strbuf_init(&node_ctx.src, 4096);
|
||||||
|
strbuf_init(&node_ctx.dst, 4096);
|
||||||
reset_dump_ctx(NULL);
|
reset_dump_ctx(NULL);
|
||||||
reset_rev_ctx(0);
|
reset_rev_ctx(0);
|
||||||
reset_node_ctx(NULL);
|
reset_node_ctx(NULL);
|
||||||
@ -472,6 +474,8 @@ void svndump_deinit(void)
|
|||||||
reset_rev_ctx(0);
|
reset_rev_ctx(0);
|
||||||
reset_node_ctx(NULL);
|
reset_node_ctx(NULL);
|
||||||
strbuf_release(&rev_ctx.log);
|
strbuf_release(&rev_ctx.log);
|
||||||
|
strbuf_release(&node_ctx.src);
|
||||||
|
strbuf_release(&node_ctx.dst);
|
||||||
if (buffer_deinit(&input))
|
if (buffer_deinit(&input))
|
||||||
fprintf(stderr, "Input error\n");
|
fprintf(stderr, "Input error\n");
|
||||||
if (ferror(stdout))
|
if (ferror(stdout))
|
||||||
|
237
vcs-svn/trp.h
237
vcs-svn/trp.h
@ -1,237 +0,0 @@
|
|||||||
/*
|
|
||||||
* C macro implementation of treaps.
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* #include <stdint.h>
|
|
||||||
* #include "trp.h"
|
|
||||||
* trp_gen(...)
|
|
||||||
*
|
|
||||||
* Licensed under a two-clause BSD-style license.
|
|
||||||
* See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TRP_H_
|
|
||||||
#define TRP_H_
|
|
||||||
|
|
||||||
#define MAYBE_UNUSED __attribute__((__unused__))
|
|
||||||
|
|
||||||
/* Node structure. */
|
|
||||||
struct trp_node {
|
|
||||||
uint32_t trpn_left;
|
|
||||||
uint32_t trpn_right;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Root structure. */
|
|
||||||
struct trp_root {
|
|
||||||
uint32_t trp_root;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Pointer/Offset conversion. */
|
|
||||||
#define trpn_pointer(a_base, a_offset) (a_base##_pointer(a_offset))
|
|
||||||
#define trpn_offset(a_base, a_pointer) (a_base##_offset(a_pointer))
|
|
||||||
#define trpn_modify(a_base, a_offset) \
|
|
||||||
do { \
|
|
||||||
if ((a_offset) < a_base##_pool.committed) { \
|
|
||||||
uint32_t old_offset = (a_offset);\
|
|
||||||
(a_offset) = a_base##_alloc(1); \
|
|
||||||
*trpn_pointer(a_base, a_offset) = \
|
|
||||||
*trpn_pointer(a_base, old_offset); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Left accessors. */
|
|
||||||
#define trp_left_get(a_base, a_field, a_node) \
|
|
||||||
(trpn_pointer(a_base, a_node)->a_field.trpn_left)
|
|
||||||
#define trp_left_set(a_base, a_field, a_node, a_left) \
|
|
||||||
do { \
|
|
||||||
trpn_modify(a_base, a_node); \
|
|
||||||
trp_left_get(a_base, a_field, a_node) = (a_left); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Right accessors. */
|
|
||||||
#define trp_right_get(a_base, a_field, a_node) \
|
|
||||||
(trpn_pointer(a_base, a_node)->a_field.trpn_right)
|
|
||||||
#define trp_right_set(a_base, a_field, a_node, a_right) \
|
|
||||||
do { \
|
|
||||||
trpn_modify(a_base, a_node); \
|
|
||||||
trp_right_get(a_base, a_field, a_node) = (a_right); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fibonacci hash function.
|
|
||||||
* The multiplier is the nearest prime to (2^32 times (√5 - 1)/2).
|
|
||||||
* See Knuth §6.4: volume 3, 3rd ed, p518.
|
|
||||||
*/
|
|
||||||
#define trpn_hash(a_node) (uint32_t) (2654435761u * (a_node))
|
|
||||||
|
|
||||||
/* Priority accessors. */
|
|
||||||
#define trp_prio_get(a_node) trpn_hash(a_node)
|
|
||||||
|
|
||||||
/* Node initializer. */
|
|
||||||
#define trp_node_new(a_base, a_field, a_node) \
|
|
||||||
do { \
|
|
||||||
trp_left_set(a_base, a_field, (a_node), ~0); \
|
|
||||||
trp_right_set(a_base, a_field, (a_node), ~0); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Internal utility macros. */
|
|
||||||
#define trpn_first(a_base, a_field, a_root, r_node) \
|
|
||||||
do { \
|
|
||||||
(r_node) = (a_root); \
|
|
||||||
if ((r_node) == ~0) \
|
|
||||||
return NULL; \
|
|
||||||
while (~trp_left_get(a_base, a_field, (r_node))) \
|
|
||||||
(r_node) = trp_left_get(a_base, a_field, (r_node)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define trpn_rotate_left(a_base, a_field, a_node, r_node) \
|
|
||||||
do { \
|
|
||||||
(r_node) = trp_right_get(a_base, a_field, (a_node)); \
|
|
||||||
trp_right_set(a_base, a_field, (a_node), \
|
|
||||||
trp_left_get(a_base, a_field, (r_node))); \
|
|
||||||
trp_left_set(a_base, a_field, (r_node), (a_node)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define trpn_rotate_right(a_base, a_field, a_node, r_node) \
|
|
||||||
do { \
|
|
||||||
(r_node) = trp_left_get(a_base, a_field, (a_node)); \
|
|
||||||
trp_left_set(a_base, a_field, (a_node), \
|
|
||||||
trp_right_get(a_base, a_field, (r_node))); \
|
|
||||||
trp_right_set(a_base, a_field, (r_node), (a_node)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define trp_gen(a_attr, a_pre, a_type, a_field, a_base, a_cmp) \
|
|
||||||
a_attr a_type MAYBE_UNUSED *a_pre##first(struct trp_root *treap) \
|
|
||||||
{ \
|
|
||||||
uint32_t ret; \
|
|
||||||
trpn_first(a_base, a_field, treap->trp_root, ret); \
|
|
||||||
return trpn_pointer(a_base, ret); \
|
|
||||||
} \
|
|
||||||
a_attr a_type MAYBE_UNUSED *a_pre##next(struct trp_root *treap, a_type *node) \
|
|
||||||
{ \
|
|
||||||
uint32_t ret; \
|
|
||||||
uint32_t offset = trpn_offset(a_base, node); \
|
|
||||||
if (~trp_right_get(a_base, a_field, offset)) { \
|
|
||||||
trpn_first(a_base, a_field, \
|
|
||||||
trp_right_get(a_base, a_field, offset), ret); \
|
|
||||||
} else { \
|
|
||||||
uint32_t tnode = treap->trp_root; \
|
|
||||||
ret = ~0; \
|
|
||||||
while (1) { \
|
|
||||||
int cmp = (a_cmp)(trpn_pointer(a_base, offset), \
|
|
||||||
trpn_pointer(a_base, tnode)); \
|
|
||||||
if (cmp < 0) { \
|
|
||||||
ret = tnode; \
|
|
||||||
tnode = trp_left_get(a_base, a_field, tnode); \
|
|
||||||
} else if (cmp > 0) { \
|
|
||||||
tnode = trp_right_get(a_base, a_field, tnode); \
|
|
||||||
} else { \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
return trpn_pointer(a_base, ret); \
|
|
||||||
} \
|
|
||||||
a_attr a_type MAYBE_UNUSED *a_pre##search(struct trp_root *treap, a_type *key) \
|
|
||||||
{ \
|
|
||||||
int cmp; \
|
|
||||||
uint32_t ret = treap->trp_root; \
|
|
||||||
while (~ret && (cmp = (a_cmp)(key, trpn_pointer(a_base, ret)))) { \
|
|
||||||
if (cmp < 0) { \
|
|
||||||
ret = trp_left_get(a_base, a_field, ret); \
|
|
||||||
} else { \
|
|
||||||
ret = trp_right_get(a_base, a_field, ret); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
return trpn_pointer(a_base, ret); \
|
|
||||||
} \
|
|
||||||
a_attr a_type MAYBE_UNUSED *a_pre##nsearch(struct trp_root *treap, a_type *key) \
|
|
||||||
{ \
|
|
||||||
int cmp; \
|
|
||||||
uint32_t ret = treap->trp_root; \
|
|
||||||
while (~ret && (cmp = (a_cmp)(key, trpn_pointer(a_base, ret)))) { \
|
|
||||||
if (cmp < 0) { \
|
|
||||||
if (!~trp_left_get(a_base, a_field, ret)) \
|
|
||||||
break; \
|
|
||||||
ret = trp_left_get(a_base, a_field, ret); \
|
|
||||||
} else { \
|
|
||||||
ret = trp_right_get(a_base, a_field, ret); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
return trpn_pointer(a_base, ret); \
|
|
||||||
} \
|
|
||||||
a_attr uint32_t MAYBE_UNUSED a_pre##insert_recurse(uint32_t cur_node, uint32_t ins_node) \
|
|
||||||
{ \
|
|
||||||
if (cur_node == ~0) { \
|
|
||||||
return ins_node; \
|
|
||||||
} else { \
|
|
||||||
uint32_t ret; \
|
|
||||||
int cmp = (a_cmp)(trpn_pointer(a_base, ins_node), \
|
|
||||||
trpn_pointer(a_base, cur_node)); \
|
|
||||||
if (cmp < 0) { \
|
|
||||||
uint32_t left = a_pre##insert_recurse( \
|
|
||||||
trp_left_get(a_base, a_field, cur_node), ins_node); \
|
|
||||||
trp_left_set(a_base, a_field, cur_node, left); \
|
|
||||||
if (trp_prio_get(left) < trp_prio_get(cur_node)) \
|
|
||||||
trpn_rotate_right(a_base, a_field, cur_node, ret); \
|
|
||||||
else \
|
|
||||||
ret = cur_node; \
|
|
||||||
} else { \
|
|
||||||
uint32_t right = a_pre##insert_recurse( \
|
|
||||||
trp_right_get(a_base, a_field, cur_node), ins_node); \
|
|
||||||
trp_right_set(a_base, a_field, cur_node, right); \
|
|
||||||
if (trp_prio_get(right) < trp_prio_get(cur_node)) \
|
|
||||||
trpn_rotate_left(a_base, a_field, cur_node, ret); \
|
|
||||||
else \
|
|
||||||
ret = cur_node; \
|
|
||||||
} \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
a_attr a_type *MAYBE_UNUSED a_pre##insert(struct trp_root *treap, a_type *node) \
|
|
||||||
{ \
|
|
||||||
uint32_t offset = trpn_offset(a_base, node); \
|
|
||||||
trp_node_new(a_base, a_field, offset); \
|
|
||||||
treap->trp_root = a_pre##insert_recurse(treap->trp_root, offset); \
|
|
||||||
return trpn_pointer(a_base, offset); \
|
|
||||||
} \
|
|
||||||
a_attr uint32_t MAYBE_UNUSED a_pre##remove_recurse(uint32_t cur_node, uint32_t rem_node) \
|
|
||||||
{ \
|
|
||||||
int cmp = a_cmp(trpn_pointer(a_base, rem_node), \
|
|
||||||
trpn_pointer(a_base, cur_node)); \
|
|
||||||
if (cmp == 0) { \
|
|
||||||
uint32_t ret; \
|
|
||||||
uint32_t left = trp_left_get(a_base, a_field, cur_node); \
|
|
||||||
uint32_t right = trp_right_get(a_base, a_field, cur_node); \
|
|
||||||
if (left == ~0) { \
|
|
||||||
if (right == ~0) \
|
|
||||||
return ~0; \
|
|
||||||
} else if (right == ~0 || trp_prio_get(left) < trp_prio_get(right)) { \
|
|
||||||
trpn_rotate_right(a_base, a_field, cur_node, ret); \
|
|
||||||
right = a_pre##remove_recurse(cur_node, rem_node); \
|
|
||||||
trp_right_set(a_base, a_field, ret, right); \
|
|
||||||
return ret; \
|
|
||||||
} \
|
|
||||||
trpn_rotate_left(a_base, a_field, cur_node, ret); \
|
|
||||||
left = a_pre##remove_recurse(cur_node, rem_node); \
|
|
||||||
trp_left_set(a_base, a_field, ret, left); \
|
|
||||||
return ret; \
|
|
||||||
} else if (cmp < 0) { \
|
|
||||||
uint32_t left = a_pre##remove_recurse( \
|
|
||||||
trp_left_get(a_base, a_field, cur_node), rem_node); \
|
|
||||||
trp_left_set(a_base, a_field, cur_node, left); \
|
|
||||||
return cur_node; \
|
|
||||||
} else { \
|
|
||||||
uint32_t right = a_pre##remove_recurse( \
|
|
||||||
trp_right_get(a_base, a_field, cur_node), rem_node); \
|
|
||||||
trp_right_set(a_base, a_field, cur_node, right); \
|
|
||||||
return cur_node; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
a_attr void MAYBE_UNUSED a_pre##remove(struct trp_root *treap, a_type *node) \
|
|
||||||
{ \
|
|
||||||
treap->trp_root = a_pre##remove_recurse(treap->trp_root, \
|
|
||||||
trpn_offset(a_base, node)); \
|
|
||||||
} \
|
|
||||||
|
|
||||||
#endif
|
|
109
vcs-svn/trp.txt
109
vcs-svn/trp.txt
@ -1,109 +0,0 @@
|
|||||||
Motivation
|
|
||||||
==========
|
|
||||||
|
|
||||||
Treaps provide a memory-efficient binary search tree structure.
|
|
||||||
Insertion/deletion/search are about as about as fast in the average
|
|
||||||
case as red-black trees and the chances of worst-case behavior are
|
|
||||||
vanishingly small, thanks to (pseudo-)randomness. The bad worst-case
|
|
||||||
behavior is a small price to pay, given that treaps are much simpler
|
|
||||||
to implement.
|
|
||||||
|
|
||||||
API
|
|
||||||
===
|
|
||||||
|
|
||||||
The trp API generates a data structure and functions to handle a
|
|
||||||
large growing set of objects stored in a pool.
|
|
||||||
|
|
||||||
The caller:
|
|
||||||
|
|
||||||
. Specifies parameters for the generated functions with the
|
|
||||||
trp_gen(static, foo_, ...) macro.
|
|
||||||
|
|
||||||
. Allocates a `struct trp_root` variable and sets it to {~0}.
|
|
||||||
|
|
||||||
. Adds new nodes to the set using `foo_insert`. Any pointers
|
|
||||||
to existing nodes cannot be relied upon any more, so the caller
|
|
||||||
might retrieve them anew with `foo_pointer`.
|
|
||||||
|
|
||||||
. Can find a specific item in the set using `foo_search`.
|
|
||||||
|
|
||||||
. Can iterate over items in the set using `foo_first` and `foo_next`.
|
|
||||||
|
|
||||||
. Can remove an item from the set using `foo_remove`.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
----
|
|
||||||
struct ex_node {
|
|
||||||
const char *s;
|
|
||||||
struct trp_node ex_link;
|
|
||||||
};
|
|
||||||
static struct trp_root ex_base = {~0};
|
|
||||||
obj_pool_gen(ex, struct ex_node, 4096);
|
|
||||||
trp_gen(static, ex_, struct ex_node, ex_link, ex, strcmp)
|
|
||||||
struct ex_node *item;
|
|
||||||
|
|
||||||
item = ex_pointer(ex_alloc(1));
|
|
||||||
item->s = "hello";
|
|
||||||
ex_insert(&ex_base, item);
|
|
||||||
item = ex_pointer(ex_alloc(1));
|
|
||||||
item->s = "goodbye";
|
|
||||||
ex_insert(&ex_base, item);
|
|
||||||
for (item = ex_first(&ex_base); item; item = ex_next(&ex_base, item))
|
|
||||||
printf("%s\n", item->s);
|
|
||||||
----
|
|
||||||
|
|
||||||
Functions
|
|
||||||
---------
|
|
||||||
|
|
||||||
trp_gen(attr, foo_, node_type, link_field, pool, cmp)::
|
|
||||||
|
|
||||||
Generate a type-specific treap implementation.
|
|
||||||
+
|
|
||||||
. The storage class for generated functions will be 'attr' (e.g., `static`).
|
|
||||||
. Generated function names are prefixed with 'foo_' (e.g., `treap_`).
|
|
||||||
. Treap nodes will be of type 'node_type' (e.g., `struct treap_node`).
|
|
||||||
This type must be a struct with at least one `struct trp_node` field
|
|
||||||
to point to its children.
|
|
||||||
. The field used to access child nodes will be 'link_field'.
|
|
||||||
. All treap nodes must lie in the 'pool' object pool.
|
|
||||||
. Treap nodes must be totally ordered by the 'cmp' relation, with the
|
|
||||||
following prototype:
|
|
||||||
+
|
|
||||||
int (*cmp)(node_type \*a, node_type \*b)
|
|
||||||
+
|
|
||||||
and returning a value less than, equal to, or greater than zero
|
|
||||||
according to the result of comparison.
|
|
||||||
|
|
||||||
node_type {asterisk}foo_insert(struct trp_root *treap, node_type \*node)::
|
|
||||||
|
|
||||||
Insert node into treap. If inserted multiple times,
|
|
||||||
a node will appear in the treap multiple times.
|
|
||||||
+
|
|
||||||
The return value is the address of the node within the treap,
|
|
||||||
which might differ from `node` if `pool_alloc` had to call
|
|
||||||
`realloc` to expand the pool.
|
|
||||||
|
|
||||||
void foo_remove(struct trp_root *treap, node_type \*node)::
|
|
||||||
|
|
||||||
Remove node from treap. Caller must ensure node is
|
|
||||||
present in treap before using this function.
|
|
||||||
|
|
||||||
node_type *foo_search(struct trp_root \*treap, node_type \*key)::
|
|
||||||
|
|
||||||
Search for a node that matches key. If no match is found,
|
|
||||||
result is NULL.
|
|
||||||
|
|
||||||
node_type *foo_nsearch(struct trp_root \*treap, node_type \*key)::
|
|
||||||
|
|
||||||
Like `foo_search`, but if the key is missing return what
|
|
||||||
would be key's successor, were key in treap (NULL if no
|
|
||||||
successor).
|
|
||||||
|
|
||||||
node_type *foo_first(struct trp_root \*treap)::
|
|
||||||
|
|
||||||
Find the first item from the treap, in sorted order.
|
|
||||||
|
|
||||||
node_type *foo_next(struct trp_root \*treap, node_type \*node)::
|
|
||||||
|
|
||||||
Find the next item.
|
|
Loading…
Reference in New Issue
Block a user