From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
Hi gitsters,
Ram last sent this series a couple of weeks ago[1], and it was
merged to pu then as rr/svn-export. Here’s another iteration
of the same for discussion, now including David Barr’s program
that demonstrates the functionality.
Patch 1 is not so closely related; it just modifies
parse_date_toffset() to keep me a little saner while using it.
Patches 2-8 are very similar to the versions Ram sent. I
expanded the commit messages, took the latest code from
git://github.com/barrbrain/svn-dump-fast-export where possible,
and added a simple example build system so one can see the
result of compiling with
make vcs-svn/lib.a
Probably more interesting is what the patches do not do:
- they do not include any tests
- they do not remove the persistent object pool functionality.
If you try this code out, be sure to remove all the .bin
files from the current directory after each run.
- they are not guaranteed to have fewer bugs than the version
Ram sent. In fact, the opposite is more likely, since the
code is only lightly tested
You can try it out with
; cd contrib/svn-fe
; wget http://github.com/barrbrain/svn-dump-fast-export/raw/master/test.dump
; make svn-fe
; ./svn-fe <test.dump
or
; make svn-fe.1
; man ./svn-fe.1
and go from there.
Any feedback is appreciated, especially on how to make this fit better
with git. I would be particularly interested in making vcs-svn/lib.a
self-sufficient --- that is, would there be a simple way to pull out
the required code from date.c?
David Barr (5):
Add memory pool library
Add string-specific memory pool
Add stream helper library
Add infrastructure to write revisions in fast-export format
Add SVN dump parser
Jason Evans (1):
Add treap implementation
Jonathan Nieder (3):
Export parse_date_basic() to convert a date string to timestamp
Introduce vcs-svn lib
Add a sample user for the svndump library
Makefile | 12 ++-
cache.h | 1 +
contrib/svn-fe/.gitignore | 3 +
contrib/svn-fe/Makefile | 63 +++++++++
contrib/svn-fe/svn-fe.c | 43 ++++++
contrib/svn-fe/svn-fe.txt | 56 ++++++++
date.c | 14 +-
vcs-svn/LICENSE | 33 +++++
vcs-svn/fast_export.c | 75 ++++++++++
vcs-svn/fast_export.h | 14 ++
vcs-svn/line_buffer.c | 93 +++++++++++++
vcs-svn/line_buffer.h | 14 ++
vcs-svn/obj_pool.h | 80 +++++++++++
vcs-svn/repo_tree.c | 335 +++++++++++++++++++++++++++++++++++++++++++++
vcs-svn/repo_tree.h | 26 ++++
vcs-svn/string_pool.c | 114 +++++++++++++++
vcs-svn/string_pool.h | 15 ++
vcs-svn/svndump.c | 289 ++++++++++++++++++++++++++++++++++++++
vcs-svn/svndump.h | 8 +
vcs-svn/trp.h | 220 +++++++++++++++++++++++++++++
vcs-svn/trp.txt | 90 ++++++++++++
21 files changed, 1589 insertions(+), 9 deletions(-)
create mode 100644 contrib/svn-fe/.gitignore
create mode 100644 contrib/svn-fe/Makefile
create mode 100644 contrib/svn-fe/svn-fe.c
create mode 100644 contrib/svn-fe/svn-fe.txt
create mode 100644 vcs-svn/LICENSE
create mode 100644 vcs-svn/fast_export.c
create mode 100644 vcs-svn/fast_export.h
create mode 100644 vcs-svn/line_buffer.c
create mode 100644 vcs-svn/line_buffer.h
create mode 100644 vcs-svn/obj_pool.h
create mode 100644 vcs-svn/repo_tree.c
create mode 100644 vcs-svn/repo_tree.h
create mode 100644 vcs-svn/string_pool.c
create mode 100644 vcs-svn/string_pool.h
create mode 100644 vcs-svn/svndump.c
create mode 100644 vcs-svn/svndump.h
create mode 100644 vcs-svn/trp.h
create mode 100644 vcs-svn/trp.txt
[1] http://thread.gmane.org/gmane.comp.version-control.git/148866
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
approxidate() is not appropriate for reading machine-written dates
because it guesses instead of erroring out on malformed dates.
parse_date() is less convenient since it returns its output as a
string. So export the underlying function that writes a timestamp.
While at it, change the return value to match the usual convention:
return 0 for success and -1 for failure.
Signed-off-by: Jonathan Nieder <redacted>
---
cache.h | 1 +
date.c | 14 ++++++--------
2 files changed, 7 insertions(+), 8 deletions(-)
@@ -800,6 +800,7 @@ const char *show_date_relative(unsigned long time, int tz,char*timebuf,size_ttimebuf_size);intparse_date(constchar*date,char*buf,intbufsize);+intparse_date_basic(constchar*date,unsignedlong*timestamp,int*offset);voiddatestamp(char*buf,intbufsize);#define approxidate(s) approxidate_careful((s), NULL)unsignedlongapproxidate_careful(constchar*,int*);
@@ -586,7 +586,7 @@ static int date_string(unsigned long date, int offset, char *buf, int len)/* Gr. strptime is crap for this; it doesn't have a way to require RFC2822(i.e.English)day/monthnames,anditdoesn'tworkcorrectlywith%z.*/-intparse_date_toffset(constchar*date,unsignedlong*timestamp,int*offset)+intparse_date_basic(constchar*date,unsignedlong*timestamp,int*offset){structtmtm;inttm_gmt;
@@ -642,17 +642,16 @@ int parse_date_toffset(const char *date, unsigned long *timestamp, int *offset)if(!tm_gmt)*timestamp-=*offset*60;-return1;/* success */+return0;/* success */}intparse_date(constchar*date,char*result,intmaxlen){unsignedlongtimestamp;intoffset;-if(parse_date_toffset(date,×tamp,&offset)>0)-returndate_string(timestamp,offset,result,maxlen);-else+if(parse_date_basic(date,×tamp,&offset))return-1;+returndate_string(timestamp,offset,result,maxlen);}enumdate_modeparse_date_format(constchar*format)
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
Teach the build system to build a separate library for the
upcoming subversion interop support.
The resulting vcs-svn/lib.a does not contain any code, nor is
it built during a normal build. This is just scaffolding for
later changes.
Signed-off-by: Jonathan Nieder <redacted>
---
Makefile | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
From: David Barr <redacted>
Add a memory pool library implemented using C macros. The obj_pool_gen()
macro creates a type-specific memory pool API.
The memory pool library is distinguished from the existing specialized
allocators in alloc.c by using a contiguous block for all allocations.
This means that on one hand, long-lived pointers have to be written as
offsets, since the base address changes as the pool grows, but on the
other hand, the entire pool can be easily written to the file system.
This allows the memory pool to persist between runs of an application.
For the svn importer, such a facility is useful because each svn
revision can copy trees and files from any previous revision. The
relevant information for all revisions has to persist somehow to
support incremental runs, and for now it is simplest to avoid relying
on the target VCS for that.
obj_pool_gen(pre, obj_t, initial_capability)
pre: Prefix for generated functions (example: string).
obj_t: Type for treap data structure (example: char).
initial_capacity: Initial size of the memory pool (example: 4096).
void pre_init(void);
Read values from a previous run to initialize the pool.
If this function is not called, the pool begins valid but empty.
uint32_t pre_alloc(uint32_t nmemb);
Reserve space for a few objects in the pool and return an
offset to the first one.
uint32_t pre_free(uint32_t nmemb);
Unreserve the last few objects reserved.
uint32_t pre_offset(obj_t *pointer);
obj_t *pre_pointer(uint32_t offset);
Convert between pointers into the in-memory pool and offsets
from the beginning (or ~0 for the NULL pointer). Pointers are
not guaranteed to remain valid after a pre_alloc() operation
or pre_reset() followed by pre_init(), but offsets are.
void pre_commit(void);
Write the pool to file. A pre_reset() followed by pre_init()
(pehaps with exit() in between) will return the pool to the
last committed state.
void pre_reset(void);
Deinitialize the pool, freeing any associated memory and
file handles.
Signed-off-by: David Barr <redacted>
Signed-off-by: Ramkumar Ramachandra <redacted>
Signed-off-by: Junio C Hamano <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
Makefile | 3 +-
vcs-svn/LICENSE | 26 +++++++++++++++++
vcs-svn/obj_pool.h | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 108 insertions(+), 1 deletions(-)
create mode 100644 vcs-svn/LICENSE
create mode 100644 vcs-svn/obj_pool.h
@@ -0,0 +1,26 @@+Copyright (C) 2010 David Barr <david.barr@cordelta.com>.+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+ notice(s), this list of conditions and the following disclaimer+ unmodified other than the allowable addition of one or more+ copyright notices.+2. Redistributions in binary form must reproduce the above copyright+ notice(s), this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
From: Jason Evans <redacted>
Provide macros to generate a type-specific treap implementation and
various functions to operate on it. It uses obj_pool.h to store memory
nodes in a treap. Previously committed nodes are never removed from
the pool; after any *_commit operation, it is assumed (correctly, in
the case of svn-fast-export) that someone else must care about them.
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.
From http://www.canonware.com/download/trp/trp_hash/trp.h
[db: Altered to reference nodes by offset from a common base pointer]
[db: Bob Jenkins' hashing implementation dropped for Knuth's]
[db: Methods unnecessary for search and insert dropped]
Signed-off-by: David Barr <redacted>
Signed-off-by: Ramkumar Ramachandra <redacted>
Signed-off-by: Junio C Hamano <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
Makefile | 2 +-
vcs-svn/LICENSE | 3 +
vcs-svn/trp.h | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
vcs-svn/trp.txt | 90 ++++++++++++++++++++++
4 files changed, 314 insertions(+), 1 deletions(-)
create mode 100644 vcs-svn/trp.h
create mode 100644 vcs-svn/trp.txt
@@ -1,6 +1,9 @@ Copyright (C) 2010 David Barr <david.barr@cordelta.com>. All rights reserved.+Copyright (C) 2008 Jason Evans <jasone@canonware.com>.+All rights reserved.+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
@@ -0,0 +1,90 @@+treap 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 and clears a `struct trp_node` variable.++. Adds new items to the set using `foo_insert`.++. 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`.++. The set is never freed.++Example:++----+struct ex_node {+ const char *s;+ struct trp_node ex_link;+};+static struct trp_root ex_base;+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.++void 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.++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,+ 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.
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
From: David Barr <redacted>
Intern strings so they can be compared by address and stored without
wasting space.
This library uses the macros in the obj_pool.h and trp.h to create a
memory pool for strings and expose an API for handling them.
Signed-off-by: David Barr <redacted>
Signed-off-by: Ramkumar Ramachandra <redacted>
Signed-off-by: Junio C Hamano <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
Makefile | 4 +-
vcs-svn/string_pool.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++
vcs-svn/string_pool.h | 15 ++++++
3 files changed, 131 insertions(+), 2 deletions(-)
create mode 100644 vcs-svn/string_pool.c
create mode 100644 vcs-svn/string_pool.h
@@ -0,0 +1,114 @@+/*+*Licensedunderatwo-clauseBSD-stylelicense.+*SeeLICENSEfordetails.+*/++#include"git-compat-util.h"+#include"trp.h"+#include"obj_pool.h"+#include"string_pool.h"++staticstructtrp_roottree={~0};++structnode{+uint32_toffset;+structtrp_nodechildren;+};++/* Two memory pools: one for struct node, and another for strings */+obj_pool_gen(node,structnode,4096);+obj_pool_gen(string,char,4096);++staticchar*node_value(structnode*node)+{+returnnode?string_pointer(node->offset):NULL;+}++staticintnode_cmp(structnode*a,structnode*b)+{+returnstrcmp(node_value(a),node_value(b));+}++/* Build a Treap from the node structure (a trp_node w/ offset) */+trp_gen(static,tree_,structnode,children,node,node_cmp);++char*pool_fetch(uint32_tentry)+{+returnnode_value(node_pointer(entry));+}++uint32_tpool_intern(char*key)+{+/* Canonicalize key */+structnode*match=NULL;+uint32_tkey_len;+if(key==NULL)+return~0;+key_len=strlen(key)+1;+structnode*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;+}+returnnode_offset(node);+}++uint32_tpool_tok_r(char*str,constchar*delim,char**saveptr)+{+char*token=strtok_r(str,delim,saveptr);+returntoken?pool_intern(token):~0;+}++voidpool_print_seq(uint32_tlen,uint32_t*seq,chardelim,FILE*stream)+{+uint32_ti;+for(i=0;i<len&&~seq[i];i++){+fputs(pool_fetch(seq[i]),stream);+if(i<len-1&&~seq[i+1])+fputc(delim,stream);+}+}++uint32_tpool_tok_seq(uint32_tmax,uint32_t*seq,char*delim,char*str)+{+char*context=NULL;+uint32_tlength=0,token=str?pool_tok_r(str,delim,&context):~0;+while(length<max){+seq[length++]=token;+if(token==~0)+break;+token=pool_tok_r(NULL,delim,&context);+}+seq[length?length-1:0]=~0;+returnlength;+}++voidpool_init(void)+{+uint32_tnode;+uint32_tstring=0;+string_init();+while(string<string_pool.size){+node=node_alloc(1);+node_pointer(node)->offset=string;+tree_insert(&tree,node_pointer(node));+string+=strlen(string_pointer(string))+1;+}+}++voidpool_commit(void)+{+string_commit();+}++voidpool_reset(void)+{+node_reset();+string_reset();+}
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
From: David Barr <redacted>
This library provides thread-unsafe fgets()- and fread()-like
functions where the caller does not have to supply a buffer. It
maintains a couple of static buffers and provides an API to use
them.
NEEDSWORK: what should buffer_copy_bytes do on error?
Signed-off-by: David Barr <redacted>
Signed-off-by: Ramkumar Ramachandra <redacted>
Signed-off-by: Junio C Hamano <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
Makefile | 5 ++-
vcs-svn/line_buffer.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++
vcs-svn/line_buffer.h | 14 +++++++
3 files changed, 110 insertions(+), 2 deletions(-)
create mode 100644 vcs-svn/line_buffer.c
create mode 100644 vcs-svn/line_buffer.h
@@ -0,0 +1,93 @@+/*+*Licensedunderatwo-clauseBSD-stylelicense.+*SeeLICENSEfordetails.+*/++#include"git-compat-util.h"++#include"line_buffer.h"+#include"obj_pool.h"++#define LINE_BUFFER_LEN 10000+#define COPY_BUFFER_LEN 4096++/* Create memory pool for char sequence of known length */+obj_pool_gen(blob,char,4096);++staticcharline_buffer[LINE_BUFFER_LEN];+staticcharbyte_buffer[COPY_BUFFER_LEN];+staticFILE*infile;++intbuffer_init(constchar*filename)+{+infile=filename?fopen(filename,"r"):stdin;+if(!infile)+return-1;+return0;+}++intbuffer_deinit()+{+fclose(infile);+return0;+}++/* Read a line without trailing newline. */+char*buffer_read_line(void)+{+char*end;+if(!fgets(line_buffer,sizeof(line_buffer),infile))+/* Error or data exhausted. */+returnNULL;+end=line_buffer+strlen(line_buffer);+if(end[-1]=='\n')+end[-1]='\0';+elseif(feof(infile))+;/* No newline at end of file. That's fine. */+else+/*+*Linewastoolong.+*Thereisprobablyasanerwaytodealwiththis,+*butfornowlet'sreturnanerror.+*/+returnNULL;+returnline_buffer;+}++char*buffer_read_string(uint32_tlen)+{+char*s;+blob_free(blob_pool.size);+s=blob_pointer(blob_alloc(len+1));+s[fread(s,1,len,infile)]='\0';+returnferror(infile)?NULL:s;+}++voidbuffer_copy_bytes(uint32_tlen)+{+uint32_tin;+while(len>0&&!feof(infile)){+in=len<COPY_BUFFER_LEN?len:COPY_BUFFER_LEN;+in=fread(byte_buffer,1,in,infile);+len-=in;+fwrite(byte_buffer,1,in,stdout);+if(ferror(infile)||ferror(stdout))+/* NEEDSWORK: handle error. */+break;+}+}++voidbuffer_skip_bytes(uint32_tlen)+{+uint32_tin;+while(len>0&&!feof(infile)&&!ferror(infile)){+in=len<COPY_BUFFER_LEN?len:COPY_BUFFER_LEN;+in=fread(byte_buffer,1,in,infile);+len-=in;+}+}++voidbuffer_reset(void)+{+blob_reset();+}
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
From: David Barr <redacted>
repo_tree maintains the exporter's state and provides a facility to to
call fast_export, which writes objects to stdout suitable for
consumption by fast-import.
The exported functions roughly correspond to Subversion FS operations.
. repo_add adds a file to the current commit.
. repo_modify adds a replacement for an existing file;
it is implemented exactly the same way, but a check could be
added later to distinguish the two cases.
. repo_copy copies a blob from a previous revision to the current
commit.
. repo_replace modifies the content of a file from the current
commit, if and only if it exists.
. repo_delete removes a file or directory from the current commit.
. repo_commit calls out to fast_export to write the current commit to
the fast-import stream in stdout.
. repo_diff is used by the fast_export module to write the changes
for a commit.
. repo_reset erases the exporter's state, so valgrind can be happy.
Signed-off-by: David Barr <redacted>
Signed-off-by: Ramkumar Ramachandra <redacted>
Signed-off-by: Junio C Hamano <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
Makefile | 5 +-
vcs-svn/fast_export.c | 75 +++++++++++
vcs-svn/fast_export.h | 14 ++
vcs-svn/repo_tree.c | 335 +++++++++++++++++++++++++++++++++++++++++++++++++
vcs-svn/repo_tree.h | 26 ++++
5 files changed, 453 insertions(+), 2 deletions(-)
create mode 100644 vcs-svn/fast_export.c
create mode 100644 vcs-svn/fast_export.h
create mode 100644 vcs-svn/repo_tree.c
create mode 100644 vcs-svn/repo_tree.h
@@ -0,0 +1,335 @@+/*+*Licensedunderatwo-clauseBSD-stylelicense.+*SeeLICENSEfordetails.+*/++#include"git-compat-util.h"++#include"string_pool.h"+#include"repo_tree.h"+#include"obj_pool.h"+#include"fast_export.h"++#include"trp.h"++structrepo_dirent{+uint32_tname_offset;+structtrp_nodechildren;+uint32_tmode;+uint32_tcontent_offset;+};++structrepo_dir{+structtrp_rootentries;+};++structrepo_commit{+uint32_troot_dir_offset;+};++/* Memory pools for commit, dir and dirent */+obj_pool_gen(commit,structrepo_commit,4096);+obj_pool_gen(dir,structrepo_dir,4096);+obj_pool_gen(dirent,structrepo_dirent,4096);++staticuint32_tactive_commit;+staticuint32_tmark;++staticintrepo_dirent_name_cmp(constvoid*a,constvoid*b);++/* Treap for directory entries */+trp_gen(static,dirent_,structrepo_dirent,children,dirent,repo_dirent_name_cmp);++uint32_tnext_blob_mark(void)+{+returnmark++;+}++staticstructrepo_dir*repo_commit_root_dir(structrepo_commit*commit)+{+returndir_pointer(commit->root_dir_offset);+}++staticstructrepo_dirent*repo_first_dirent(structrepo_dir*dir)+{+returndirent_first(&dir->entries);+}++staticintrepo_dirent_name_cmp(constvoid*a,constvoid*b)+{+conststructrepo_dirent*dirent1=a,*dirent2=b;+uint32_ta_offset=dirent1->name_offset;+uint32_tb_offset=dirent2->name_offset;+return(a_offset>b_offset)-(a_offset<b_offset);+}++staticintrepo_dirent_is_dir(structrepo_dirent*dirent)+{+returndirent!=NULL&&dirent->mode==REPO_MODE_DIR;+}++staticstructrepo_dir*repo_dir_from_dirent(structrepo_dirent*dirent)+{+if(!repo_dirent_is_dir(dirent))+returnNULL;+returndir_pointer(dirent->content_offset);+}++staticstructrepo_dir*repo_clone_dir(structrepo_dir*orig_dir)+{+uint32_torig_o,new_o;+orig_o=dir_offset(orig_dir);+if(orig_o>=dir_pool.committed)+returnorig_dir;+new_o=dir_alloc(1);+orig_dir=dir_pointer(orig_o);+*dir_pointer(new_o)=*orig_dir;+returndir_pointer(new_o);+}++staticstructrepo_dirent*repo_read_dirent(uint32_trevision,uint32_t*path)+{+uint32_tname=0;+structrepo_dirent*key=dirent_pointer(dirent_alloc(1));+structrepo_dir*dir=NULL;+structrepo_dirent*dirent=NULL;+dir=repo_commit_root_dir(commit_pointer(revision));+while(~(name=*path++)){+key->name_offset=name;+dirent=dirent_search(&dir->entries,key);+if(dirent==NULL||!repo_dirent_is_dir(dirent))+break;+dir=repo_dir_from_dirent(dirent);+}+dirent_free(1);+returndirent;+}++staticvoidrepo_write_dirent(uint32_t*path,uint32_tmode,+uint32_tcontent_offset,uint32_tdel)+{+uint32_tname,revision,dir_o=~0,parent_dir_o=~0;+structrepo_dir*dir;+structrepo_dirent*key;+structrepo_dirent*dirent=NULL;+revision=active_commit;+dir=repo_commit_root_dir(commit_pointer(revision));+dir=repo_clone_dir(dir);+commit_pointer(revision)->root_dir_offset=dir_offset(dir);+while(~(name=*path++)){+parent_dir_o=dir_offset(dir);++key=dirent_pointer(dirent_alloc(1));+key->name_offset=name;++dirent=dirent_search(&dir->entries,key);+if(dirent==NULL)+dirent=key;+else+dirent_free(1);++if(dirent==key){+dirent->mode=REPO_MODE_DIR;+dirent->content_offset=0;+dirent_insert(&dir->entries,dirent);+}++if(dirent_offset(dirent)<dirent_pool.committed){+dir_o=repo_dirent_is_dir(dirent)?+dirent->content_offset:~0;+dirent_remove(&dir->entries,dirent);+dirent=dirent_pointer(dirent_alloc(1));+dirent->name_offset=name;+dirent->mode=REPO_MODE_DIR;+dirent->content_offset=dir_o;+dirent_insert(&dir->entries,dirent);+}++dir=repo_dir_from_dirent(dirent);+dir=repo_clone_dir(dir);+dirent->content_offset=dir_offset(dir);+}+if(dirent==NULL)+return;+dirent->mode=mode;+dirent->content_offset=content_offset;+if(del&&~parent_dir_o)+dirent_remove(&dir_pointer(parent_dir_o)->entries,dirent);+}++uint32_trepo_copy(uint32_trevision,uint32_t*src,uint32_t*dst)+{+uint32_tmode=0,content_offset=0;+structrepo_dirent*src_dirent;+src_dirent=repo_read_dirent(revision,src);+if(src_dirent!=NULL){+mode=src_dirent->mode;+content_offset=src_dirent->content_offset;+repo_write_dirent(dst,mode,content_offset,0);+}+returnmode;+}++voidrepo_add(uint32_t*path,uint32_tmode,uint32_tblob_mark)+{+repo_write_dirent(path,mode,blob_mark,0);+}++uint32_trepo_replace(uint32_t*path,uint32_tblob_mark)+{+uint32_tmode=0;+structrepo_dirent*src_dirent;+src_dirent=repo_read_dirent(active_commit,path);+if(src_dirent!=NULL){+mode=src_dirent->mode;+repo_write_dirent(path,mode,blob_mark,0);+}+returnmode;+}++voidrepo_modify(uint32_t*path,uint32_tmode,uint32_tblob_mark)+{+structrepo_dirent*src_dirent;+src_dirent=repo_read_dirent(active_commit,path);+if(src_dirent!=NULL&&blob_mark==0)+blob_mark=src_dirent->content_offset;+repo_write_dirent(path,mode,blob_mark,0);+}++voidrepo_delete(uint32_t*path)+{+repo_write_dirent(path,0,0,1);+}++staticvoidrepo_git_add_r(uint32_tdepth,uint32_t*path,structrepo_dir*dir);++staticvoidrepo_git_add(uint32_tdepth,uint32_t*path,structrepo_dirent*dirent)+{+if(repo_dirent_is_dir(dirent))+repo_git_add_r(depth,path,repo_dir_from_dirent(dirent));+else+fast_export_modify(depth,path,+dirent->mode,dirent->content_offset);+}++staticvoidrepo_git_add_r(uint32_tdepth,uint32_t*path,structrepo_dir*dir)+{+structrepo_dirent*de=repo_first_dirent(dir);+while(de){+path[depth]=de->name_offset;+repo_git_add(depth+1,path,de);+de=dirent_next(&dir->entries,de);+}+}++staticvoidrepo_diff_r(uint32_tdepth,uint32_t*path,structrepo_dir*dir1,+structrepo_dir*dir2)+{+structrepo_dirent*de1,*de2;+de1=repo_first_dirent(dir1);+de2=repo_first_dirent(dir2);++while(de1&&de2){+if(de1->name_offset<de2->name_offset){+path[depth]=de1->name_offset;+fast_export_delete(depth+1,path);+de1=dirent_next(&dir1->entries,de1);+continue;+}+if(de1->name_offset>de2->name_offset){+path[depth]=de2->name_offset;+repo_git_add(depth+1,path,de2);+de2=dirent_next(&dir2->entries,de2);+continue;+}+path[depth]=de1->name_offset;++if(de1->mode==de2->mode&&+de1->content_offset==de2->content_offset){+;/* No change. */+}elseif(repo_dirent_is_dir(de1)&&repo_dirent_is_dir(de2)){+repo_diff_r(depth+1,path,+repo_dir_from_dirent(de1),+repo_dir_from_dirent(de2));+}elseif(!repo_dirent_is_dir(de1)&&!repo_dirent_is_dir(de2)){+repo_git_add(depth+1,path,de2);+}else{+fast_export_delete(depth+1,path);+repo_git_add(depth+1,path,de2);+}+de1=dirent_next(&dir1->entries,de1);+de2=dirent_next(&dir2->entries,de2);+}+while(de1){+path[depth]=de1->name_offset;+fast_export_delete(depth+1,path);+de1=dirent_next(&dir1->entries,de1);+}+while(de2){+path[depth]=de2->name_offset;+repo_git_add(depth+1,path,de2);+de2=dirent_next(&dir2->entries,de2);+}+}++staticuint32_tpath_stack[REPO_MAX_PATH_DEPTH];++voidrepo_diff(uint32_tr1,uint32_tr2)+{+repo_diff_r(0,+path_stack,+repo_commit_root_dir(commit_pointer(r1)),+repo_commit_root_dir(commit_pointer(r2)));+}++voidrepo_commit(uint32_trevision,uint32_tauthor,char*log,uint32_tuuid,+uint32_turl,unsignedlongtimestamp)+{+fast_export_commit(revision,author,log,uuid,url,timestamp);+pool_commit();+dirent_commit();+dir_commit();+commit_commit();+active_commit=commit_alloc(1);+commit_pointer(active_commit)->root_dir_offset=+commit_pointer(active_commit-1)->root_dir_offset;+}++staticvoidmark_init(void)+{+uint32_ti;+mark=0;+for(i=0;i<dirent_pool.size;i++)+if(!repo_dirent_is_dir(dirent_pointer(i))&&+dirent_pointer(i)->content_offset>mark)+mark=dirent_pointer(i)->content_offset;+mark++;+}++voidrepo_init(){+pool_init();+commit_init();+dir_init();+dirent_init();+mark_init();+if(commit_pool.size==0){+/* Create empty tree for commit 0. */+commit_alloc(1);+commit_pointer(0)->root_dir_offset=dir_alloc(1);+dir_pointer(0)->entries.trp_root=~0;+dir_commit();+commit_commit();+}+/* Preallocate next commit, ready for changes. */+active_commit=commit_alloc(1);+commit_pointer(active_commit)->root_dir_offset=+commit_pointer(active_commit-1)->root_dir_offset;+}++voidrepo_reset(void)+{+pool_reset();+commit_reset();+dir_reset();+dirent_reset();+}
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
From: David Barr <redacted>
svndump parses data that is in SVN dumpfile format produced by
`svnadmin dump` with the help of line_buffer and uses repo_tree and
fast_export to emit a git fast-import stream.
Based roughly on com.hydrografix.svndump 0.92 from the SvnToCCase
project at <http://svn2cc.sarovar.org/>, by Stefan Hegny and
others.
Signed-off-by: David Barr <redacted>
Signed-off-by: Ramkumar Ramachandra <redacted>
Signed-off-by: Junio C Hamano <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
Makefile | 5 +-
vcs-svn/LICENSE | 4 +
vcs-svn/svndump.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++
vcs-svn/svndump.h | 8 ++
4 files changed, 304 insertions(+), 2 deletions(-)
create mode 100644 vcs-svn/svndump.c
create mode 100644 vcs-svn/svndump.h
@@ -4,6 +4,10 @@ All rights reserved. Copyright (C) 2008 Jason Evans <jasone@canonware.com>. All rights reserved.+Copyright (C) 2005 Stefan Hegny, hydrografix Consulting GmbH,+Frankfurt/Main, Germany+and others, see http://svn2cc.sarovar.org+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
The svn-fe tool takes a Subversion dump file as input and produces
a fast-import stream as output. This can be useful as a low-level
tool in building other importers, or for debugging the vcs-svn
library.
make svn-fe
make svn-fe.1
to test.
NEEDSWORK: litters cwd with useless .bin files.
But I hope it is enough to show the idea.
Signed-off-by: Jonathan Nieder <redacted>
---
Thanks for reading. Thoughts welcome.
contrib/svn-fe/.gitignore | 3 ++
contrib/svn-fe/Makefile | 63 +++++++++++++++++++++++++++++++++++++++++++++
contrib/svn-fe/svn-fe.c | 43 ++++++++++++++++++++++++++++++
contrib/svn-fe/svn-fe.txt | 56 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 165 insertions(+), 0 deletions(-)
create mode 100644 contrib/svn-fe/.gitignore
create mode 100644 contrib/svn-fe/Makefile
create mode 100644 contrib/svn-fe/svn-fe.c
create mode 100644 contrib/svn-fe/svn-fe.txt
@@ -0,0 +1,56 @@+svn-fe(1)+=========++NAME+----+svn-fe - convert an SVN "dumpfile" to a fast-import stream++SYNOPSIS+--------+svnadmin dump --incremental REPO | svn-fe [url] | git fast-import++DESCRIPTION+-----------+Converts a textual representation of a Subversion repository into+input suitable for git-fast-import(1) and similar importers.++INPUT FORMAT+------------+Subversion's repository dump format is documented in full in+`notes/dump-load-format.txt` from the Subversion source tree.+Files in this format can be generated using the 'svnadmin dump' or+'svk admin dump' command.++OUTPUT FORMAT+-------------+The fast-import format is documented by the git-fast-import(1)+manual page.++NOTES+-----+Subversion dumps do not record a separate author and committer for+each revision, nor a separate display name and email address for+each author. Like git-svn(1), 'svn-fe' will use the name++---------+user <user@UUID>+---------++as committer, where 'user' is the value of the `svn:author` property+and 'UUID' the repository's identifier.++To support incremental imports, 'svn-fe' will put a `git-svn-id`+line at the end of each commit log message if passed an url on the+command line. This line has the form `git-svn-id: URL@REVNO UUID`.++Empty directories and unknown properties are silently discarded.++The resulting repository will generally require further processing+to put each project in its own repository and to separate the history+of each branch. The 'git filter-branch --subdirectory-filter' command+may be useful for this purpose.++SEE ALSO+--------+git-svn(1), svn2git(1), svk(1), git-filter-branch(1), git-fast-import(1),+https://svn.apache.org/repos/asf/subversion/trunk/notes/dump-load-format.txt
Ram last sent this series a couple of weeks ago[1], and it was
merged to pu then as rr/svn-export. Here’s another iteration
of the same for discussion, now including David Barr’s program
that demonstrates the functionality.
There's a lot of work happening in the exporter and the series will
probably need to be re-rolled again: I recommend the following.
1. Review this series thoroughly, but don't actually merge it because
it's going to be re-rolled soon.
2. Split the series in two: The infrastructure part in vcs-svn/ will
be re-rolled later. Another part for contrib/ should be made into a
separate series and merged.
3. As soon as the client is complete, I'll roll a series that puts it
in vcs-svn/ (infrastructure again).
4. Finally, I'll roll out a series for the remote helper itself that
puts it in $GIT_ROOT.
To summarize, there should be four series:
1. David's exporter in vcs-svn/ (yet to be re-rolled): Either Jonathan
or I will handle this.
2. David's independent svn-fe program in contrib/: Jonathan will handle this.
3. The RA client to generate a full-text dumpfile on-the-fly: This
isn't done yet; as soon as it's finished, I'll roll a series.
4. The remote helper: This done, but it doesn't make sense to send
this in before everything else has been merged.
-- Ram
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
Ramkumar Ramachandra wrote:
There's a lot of work happening in the exporter and the series will
probably need to be re-rolled again: I recommend the following.
1. Review this series thoroughly, but don't actually merge it because
it's going to be re-rolled soon.
To be more specific: although svndump.c, fast_export.c, and
repo_tree.c may need to be a bit slushy now while we figure out the
incremental import story, the rest of the series is not likely to
change much in broad strokes. I get the impression that facilities
like strbuf and string_list benefit greatly from early review, so in
particular let me mention the facilities this series adds:
. obj_pool, an array of fixed-size records that can be written to
disk. This is just begging to be implemented with mmap; maybe
in the future the compat/mmap.c shim can be tweaked to support
faking it.
. treap, a multiset datastructure built on top of obj_pool. I
suspect API cleanups would be welcome here: it’s a bit more
unwieldly than string_list at the moment.
. string_pool, a collection of interned strings built on top of
treap.
. line_buffer, a simple fread()/fgets() wrapper with a static buffer.
I would find feedback on these (or patches :)) especially welcome.
Jonathan
Hi Jonathan,
This specific patch is clear. I have some issues with some of the
other parts in the series.
Jonathan Nieder wrote:
approxidate() is not appropriate for reading machine-written dates
because it guesses instead of erroring out on malformed dates.
parse_date() is less convenient since it returns its output as a
string. So export the underlying function that writes a timestamp.
Right. I couldn't justify exposing it in the series that's in master now.
While at it, change the return value to match the usual convention:
return 0 for success and -1 for failure.
Since I'm to blame for this change,
Acked-by: Ramkumar Ramachandra <redacted>
-- Ram
From: David Barr <redacted>
Add a memory pool library implemented using C macros. The obj_pool_gen()
macro creates a type-specific memory pool API.
Until some sort of mmap is implemented, I doubt we can do much better
than this. By marking all the generated functions MAYBE_UNUSED, we're
actually suppressing more warnings than intended. Maybe we can avoid
it and somehow find a way to mark only those functions that are really
unused? Perhaps an extra parameter in obj_pool_gen?
-- Ram
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
Hi Ram,
Ramkumar Ramachandra wrote:
By marking all the generated functions MAYBE_UNUSED, we're
actually suppressing more warnings than intended. Maybe we can avoid
it and somehow find a way to mark only those functions that are really
unused?
If we used templates instead of macros, a smart compiler would notice
which functions are _never_ used. But sticking to C, I think it is
fine to rely on humans checking by hand for now. (FWIW no obj_pool
functions are unused at the moment.)
I tried leaving out the MAYBE_UNUSED for foo_init() before I realized
that calling it is optional.
Perhaps an extra parameter in obj_pool_gen?
Filling out such a list for each caller sounds to me like more trouble
than it’s worth.
Jonathan
From: Jason Evans <redacted>
Provide macros to generate a type-specific treap implementation and
various functions to operate on it. It uses obj_pool.h to store memory
nodes in a treap. Previously committed nodes are never removed from
the pool; after any *_commit operation, it is assumed (correctly, in
the case of svn-fast-export) that someone else must care about them.
This is likely to change in a few days. David is currently working on
a Java implementation of a immutable ternary treap and will
re-implement it as C macros. See the ternary-treap branch.
Interesting how you've shown this in every patch :)
+/*
+ * 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.
+ */
Um, is it alright to put non-ascii characters in a file containing
code? I haven't seen such a thing in any of the other files. Will some
old compilers complain while parsing?
quoted hunk
--- /dev/null+++ b/vcs-svn/trp.txt
@@ -0,0 +1,90 @@+treap API
The documentation is good, but I don't see it merged into the tree.
Perhaps send a patch to David? Also, you might want to include the
technical explanation for using treaps from the commit message here?
-- Ram
Intern strings so they can be compared by address and stored without
wasting space.
It's unlikely that this'll change much, if at all. It should go in
without any issues. I'm not sure this is appropriate since I've
already signed off, but anyway:
Reviewed-by: Ramkumar Ramachandra <redacted>
-- Ram
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
Ramkumar Ramachandra wrote:
David is currently working on
a Java implementation of a immutable ternary treap and will
re-implement it as C macros. See the ternary-treap branch.
I assume his blog post from a week or so ago[1] is relevant.
The trie-based version should be interesting but less generic (which
is fine, since we only have two users and both use string keys).
Interesting how you've shown this in every patch :)
It would have been less messy to use
$(VCSSVN_OBJS): \
vcs-svn/obj_pool.h \
vcs-svn/trp.h \
... \
or
$(VCSSVN_OBJS): vcs-svn/obj_pool.h
$(VCSSVN_OBJS): vcs-svn/trp.h
...
I just can’t bring myself to care much. :)
quoted
+/*
+ * 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.
+ */
Um, is it alright to put non-ascii characters in a file containing
code?
Yes, UTF-8 is sometimes used in comments for people’s names. See
builtin/branch.c, for example.
The documentation is good, but I don't see it merged into the tree.
Perhaps send a patch to David?
Yes. I should send some other patches, too, to minimize the delta.
Also, you might want to include the
technical explanation for using treaps from the commit message here?
repo_tree maintains the exporter's state and provides a facility to to
call fast_export, which writes objects to stdout suitable for
consumption by fast-import.
These files will also change significantly in a few days- see the
ternary_treap branch.
The exported functions roughly correspond to Subversion FS operations.
This description is sufficient for the commit message.
. repo_add adds a file to the current commit.
. repo_modify adds a replacement for an existing file;
it is implemented exactly the same way, but a check could be
added later to distinguish the two cases.
. repo_copy copies a blob from a previous revision to the current
commit.
. repo_replace modifies the content of a file from the current
commit, if and only if it exists.
. repo_delete removes a file or directory from the current commit.
. repo_commit calls out to fast_export to write the current commit to
the fast-import stream in stdout.
. repo_diff is used by the fast_export module to write the changes
for a commit.
. repo_reset erases the exporter's state, so valgrind can be happy.
This is like API documentation- should it go into the commit message?
Maybe put this in a a dedicated repo_tree.txt like trp.h?
-- Ram
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
Ramkumar Ramachandra wrote:
This is like API documentation- should it go into the commit message?
Maybe put this in a a dedicated repo_tree.txt like trp.h?
Good question. The answer depends on whether we want to keep it
maintained.
Since this is not meant to be a general-purpose API, I thought it
simplest to document it in the commit message and let future commit
messages describe the purpose of future changes. We are not
approaching any limit on the length of a commit object, after all.
Jonathan
If we used templates instead of macros, a smart compiler would notice
which functions are _never_ used. But sticking to C, I think it is
fine to rely on humans checking by hand for now. (FWIW no obj_pool
functions are unused at the moment.)
Filling out such a list for each caller sounds to me like more trouble
than it’s worth.
Okay, I have an idea. We'll document it as a comment so people will be
able to see which exact functions were unused in this import. The
following functions are unused: blob_init, blob_offset, blob_commit,
commit_free, commit_offset, dir_free, node_init, node_commit,
string_offset, tree_first, tree_next, tree_remove, log_init,
log_offset, and log_commit.
-- Ram
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
On Thu, Jun 24, 2010 at 09:29:29PM +0200, Ramkumar Ramachandra wrote:
Jonathan Nieder wrote:
quoted
. repo_reset erases the exporter's state, so valgrind can be happy.
This is like API documentation- should it go into the commit message?
A more terse summary, to save readers time:
. repo_add, repo_modify, repo_copy, repo_replace, and repo_delete
update the current commit, based roughly on the corresponding
Subversion FS operation.
. repo_commit calls out to fast_export to write the current commit to
the fast-import stream in stdout.
. repo_diff is used by the fast_export module to write the changes
for a commit.
. repo_reset erases the exporter's state, so valgrind can be happy.
Jonathan
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
Ramkumar Ramachandra wrote:
The
following functions are unused: blob_init, blob_offset, blob_commit,
commit_free, commit_offset, dir_free, node_init, node_commit,
string_offset, tree_first, tree_next, tree_remove, log_init,
log_offset, and log_commit.
Thanks for this list. Do you think it’s worth automating its
production? i.e., a masochistic person could write a script to
compile with the __attribute__((unused)) suppressed, parse warnings to
find unused functions, and then take an intersection of sets to
confirm that no family of functions is unused.
Jonathan
NEEDSWORK: litters cwd with useless .bin files.
But I hope it is enough to show the idea.
How do you propose we solve this? Maybe using a generic
$TEMP_DIRECTORY like /tmp in Unix and then getting rid of the files
after the export is complete?
+QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
+QUIET_SUBDIR1 =
I saw this in the Git Makefile too, but I didn't understand the logic
behind it. Could you explain it to me?
Note: I couldn't understand most of the Makefile, so I just skipped it
when I found similar declarations in the Git Makefile.
If the user doesn't have a clue about SVN, they won't know what REPO
is here: Without knowing anything about svnadmin, I'd naively try it
with a remote repository. Maybe include a note about having to mirror
a complete repository locally using svnsync (or otherwise) first?
+Converts a textual representation of a Subversion repository into
+input suitable for git-fast-import(1) and similar importers.
To be more specific, "Subversion dumpfile (version: 2)" from FILE(1).
-- Ram
Thanks for this list. Do you think it’s worth automating its
production? i.e., a masochistic person could write a script to
compile with the __attribute__((unused)) suppressed, parse warnings to
find unused functions, and then take an intersection of sets to
confirm that no family of functions is unused.
Er, I think that's a bit of an overkill :p
Someone editing the code can always suppress MAYBE_UNUSED and check
with our list of unused functions in the comment by hand.
-- Ram
Teach the build system to build a separate library for the
upcoming subversion interop support.
The resulting vcs-svn/lib.a does not contain any code, nor is
it built during a normal build. This is just scaffolding for
later changes.
This is very elegant indeed!
Acked-by: Ramkumar Ramachandra <redacted>
-- Ram
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
Ramkumar Ramachandra wrote:
Jonathan Nieder wrote:
quoted
NEEDSWORK: litters cwd with useless .bin files.
But I hope it is enough to show the idea.
How do you propose we solve this?
Turn off persistence until it is ready. At that point, we will need
to access the target git repo anyway, so we can keep extra metadata in
the .git directory.
quoted
+QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
+QUIET_SUBDIR1 =
I saw this in the Git Makefile too, but I didn't understand the logic
behind it. Could you explain it to me?
See commit 74f2b2a.
Summary: this produces the
CC foo.o
lines. The idea is that long command lines distract from what is more
important, which is the compiler output. The behavior can be turned
off with “make V=1” or “make -s”.
That's a huge license header applies just to the trivial five-line
program, right? Is it necessary at all?
I dunno. I included the license header instead of refering to LICENSE
because this file tends to be installed in /usr/share/doc/git/contrib
and LICENSE does not.
Maybe the file should get a simpler license? e.g.:
This file is in the public domain.
You may freely use, modify, distribute, and relicense it.
If the user doesn't have a clue about SVN, they won't know what REPO
is here: Without knowing anything about svnadmin, I'd naively try it
with a remote repository. Maybe include a note about having to mirror
a complete repository locally using svnsync (or otherwise) first?
Sounds reasonable. Care to suggest wording?
quoted
+Converts a textual representation of a Subversion repository into
+input suitable for git-fast-import(1) and similar importers.
To be more specific, "Subversion dumpfile (version: 2)" from FILE(1).
svndump parses data that is in SVN dumpfile format produced by
`svnadmin dump` with the help of line_buffer and uses repo_tree and
fast_export to emit a git fast-import stream.
This hasn't changed from last time, and isn't expected to change in
future. Should go in without any issues, although I'd love it if we
could somehow refactor the huge if-else tree. Again, I'm not sure if
this is appropriate since I've already signed off:
Reviewed-by: Ramkumar Ramachandra <redacted>
-- Ram
Turn off persistence until it is ready. At that point, we will need
to access the target git repo anyway, so we can keep extra metadata in
the .git directory.
Unfortunately, turning off persistence isn't so easy now because the
branch has been merged into master now, and it's difficult to sort out
just the commits that correspond to persistence and rebase.
Yes, the remote helper can use the .git directory, but I thought we
wanted to keep this in contrib/ even after the remote helper is
merged?
See commit 74f2b2a.
Summary: this produces the
CC foo.o
lines. The idea is that long command lines distract from what is more
important, which is the compiler output. The behavior can be turned
off with “make V=1” or “make -s”.
Ah. Black magic :)
Maybe the file should get a simpler license? e.g.:
This file is in the public domain.
You may freely use, modify, distribute, and relicense it.
Yes, I like this.
Sounds reasonable. Care to suggest wording?
Something along "REPO is a path to a Subversion repository mirrored on
the local disk. Remote Subversion repositories can be mirrored on
local disk using the `svnsync` command."
Do version 3 dumpfiles fail?
Yes, they do. We aren't parsing the extra headers anywhere, and
deltified dumps aren't supported.
-- Ram
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
Ramkumar Ramachandra wrote:
Unfortunately, turning off persistence isn't so easy now
Hmm, couldn’t one just leave out some pool_init() calls?
Of course, that would make pool_init() and related functionality unused,
and we may or may not want to remove it while at it.
Yes, the remote helper can use the .git directory, but I thought we
wanted to keep this in contrib/ even after the remote helper is
merged?
For incremental imports, I suspect the standalone svn-fe is going to
need to invoke ‘git fast-import’ itself, which implies knowledge of
the location of the .git directory.
For undeltified nonincremental imports, there is no problem. :)
Jonathan Nieder wrote:
quoted
Maybe the file should get a simpler license? e.g.:
This file is in the public domain.
You may freely use, modify, distribute, and relicense it.
Yes, I like this.
David, would this be okay? (for the short svn-fe.c file only)
quoted
Do version 3 dumpfiles fail?
Yes, they do. We aren't parsing the extra headers anywhere, and
deltified dumps aren't supported.
A more terse summary, to save readers time:
. repo_add, repo_modify, repo_copy, repo_replace, and repo_delete
update the current commit, based roughly on the corresponding
Subversion FS operation.
. repo_commit calls out to fast_export to write the current commit to
the fast-import stream in stdout.
. repo_diff is used by the fast_export module to write the changes
for a commit.
. repo_reset erases the exporter's state, so valgrind can be happy.
This library provides thread-unsafe fgets()- and fread()-like
functions where the caller does not have to supply a buffer. It
maintains a couple of static buffers and provides an API to use
them.
Few (no?) changes since last time.
Just a quick reminder: eventually, we might be able to factor out this
line_buffer thing completely; it's quite non-trivial though.
-- Ram
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:00
Ramkumar Ramachandra wrote:
Jonathan Nieder wrote:
quoted
This library provides thread-unsafe fgets()- and fread()-like
functions where the caller does not have to supply a buffer. It
maintains a couple of static buffers and provides an API to use
them.
Few (no?) changes since last time.
I simplified it a bit by getting rid of pushback.
static uint32_t line_buffer_len = 0;
static uint32_t line_len = 0;
Sorry, I should have mentioned so.
Jonathan
From: Sam Vilain <hidden> Date: 2016-06-15 22:49:01
On Thu, 2010-06-24 at 06:07 -0500, Jonathan Nieder wrote:
+To support incremental imports, 'svn-fe' will put a `git-svn-id`
+line at the end of each commit log message if passed an url on the
+command line. This line has the form `git-svn-id: URL@REVNO UUID`.
If you are importing from an svk mirror or svnsync mirror, it will be
required to rewrite this portion.
+Empty directories and unknown properties are silently discarded.
Yeah. These should probably be carried over in this pass. Revision
properties could possibly be converted to extra RFC822-style headers in
the commit message. Directory properties can go under $dir/.svnfe-props
(use an empty file to mark empty directories) and $filename.svnfe-props
- it is up to the data mining phase whether it wants to actually do
anything with that data later.
Sam