Skip to content

Commit

Permalink
Merge branch 'svn-fe' of git://repo.or.cz/git/jrn
Browse files Browse the repository at this point in the history
* 'svn-fe' of git://repo.or.cz/git/jrn:
  vcs-svn: use strchr to find RFC822 delimiter
  vcs-svn: implement perfect hash for top-level keys
  vcs-svn: implement perfect hash for node-prop keys
  vcs-svn: use strbuf for author, UUID, and URL
  vcs-svn: use strbuf for revision log
  vcs-svn: improve reporting of input errors
  vcs-svn: make buffer_copy_bytes return length read
  vcs-svn: make buffer_skip_bytes return length read
  vcs-svn: improve support for reading large files
  vcs-svn: allow input errors to be detected promptly
  vcs-svn: simplify repo_modify_path and repo_copy
  vcs-svn: handle_node: use repo_read_path
  vcs-svn: introduce repo_read_path to check the content at a path
  • Loading branch information
Junio C Hamano committed Mar 23, 2011
2 parents 1ea9f9d + 41b9dd9 commit 785d698
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 172 deletions.
27 changes: 18 additions & 9 deletions vcs-svn/fast_export.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,24 @@ void fast_export_modify(uint32_t depth, uint32_t *path, uint32_t mode,
}

static char gitsvnline[MAX_GITSVN_LINE_LEN];
void fast_export_commit(uint32_t revision, uint32_t author, char *log,
uint32_t uuid, uint32_t url,
void fast_export_commit(uint32_t revision, const char *author, char *log,
const char *uuid, const char *url,
unsigned long timestamp)
{
if (!log)
log = "";
if (~uuid && ~url) {
if (*uuid && *url) {
snprintf(gitsvnline, MAX_GITSVN_LINE_LEN,
"\n\ngit-svn-id: %s@%"PRIu32" %s\n",
pool_fetch(url), revision, pool_fetch(uuid));
url, revision, uuid);
} else {
*gitsvnline = '\0';
}
printf("commit refs/heads/master\n");
printf("committer %s <%s@%s> %ld +0000\n",
~author ? pool_fetch(author) : "nobody",
~author ? pool_fetch(author) : "nobody",
~uuid ? pool_fetch(uuid) : "local", timestamp);
*author ? author : "nobody",
*author ? author : "nobody",
*uuid ? uuid : "local", timestamp);
printf("data %"PRIu32"\n%s%s\n",
(uint32_t) (strlen(log) + strlen(gitsvnline)),
log, gitsvnline);
Expand All @@ -63,14 +63,23 @@ void fast_export_commit(uint32_t revision, uint32_t author, char *log,
printf("progress Imported commit %"PRIu32".\n\n", revision);
}

static void die_short_read(struct line_buffer *input)
{
if (buffer_ferror(input))
die_errno("error reading dump file");
die("invalid dump: unexpected end of file");
}

void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len, struct line_buffer *input)
{
if (mode == REPO_MODE_LNK) {
/* svn symlink blobs start with "link " */
buffer_skip_bytes(input, 5);
len -= 5;
if (buffer_skip_bytes(input, 5) != 5)
die_short_read(input);
}
printf("blob\nmark :%"PRIu32"\ndata %"PRIu32"\n", mark, len);
buffer_copy_bytes(input, len);
if (buffer_copy_bytes(input, len) != len)
die_short_read(input);
fputc('\n', stdout);
}
5 changes: 3 additions & 2 deletions vcs-svn/fast_export.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
void fast_export_delete(uint32_t depth, uint32_t *path);
void fast_export_modify(uint32_t depth, uint32_t *path, uint32_t mode,
uint32_t mark);
void fast_export_commit(uint32_t revision, uint32_t author, char *log,
uint32_t uuid, uint32_t url, unsigned long timestamp);
void fast_export_commit(uint32_t revision, const char *author, char *log,
const char *uuid, const char *url,
unsigned long timestamp);
void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len,
struct line_buffer *input);

Expand Down
36 changes: 21 additions & 15 deletions vcs-svn/line_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ long buffer_tmpfile_prepare_to_read(struct line_buffer *buf)
return pos;
}

int buffer_ferror(struct line_buffer *buf)
{
return ferror(buf->infile);
}

int buffer_read_char(struct line_buffer *buf)
{
return fgetc(buf->infile);
Expand Down Expand Up @@ -99,31 +104,32 @@ void buffer_read_binary(struct line_buffer *buf,
strbuf_fread(sb, size, buf->infile);
}

void buffer_copy_bytes(struct line_buffer *buf, uint32_t len)
off_t buffer_copy_bytes(struct line_buffer *buf, off_t nbytes)
{
char byte_buffer[COPY_BUFFER_LEN];
uint32_t in;
while (len > 0 && !feof(buf->infile) && !ferror(buf->infile)) {
in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
off_t done = 0;
while (done < nbytes && !feof(buf->infile) && !ferror(buf->infile)) {
off_t len = nbytes - done;
size_t in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
in = fread(byte_buffer, 1, in, buf->infile);
len -= in;
done += in;
fwrite(byte_buffer, 1, in, stdout);
if (ferror(stdout)) {
buffer_skip_bytes(buf, len);
return;
}
if (ferror(stdout))
return done + buffer_skip_bytes(buf, nbytes - done);
}
return done;
}

void buffer_skip_bytes(struct line_buffer *buf, uint32_t len)
off_t buffer_skip_bytes(struct line_buffer *buf, off_t nbytes)
{
char byte_buffer[COPY_BUFFER_LEN];
uint32_t in;
while (len > 0 && !feof(buf->infile) && !ferror(buf->infile)) {
in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
in = fread(byte_buffer, 1, in, buf->infile);
len -= in;
off_t done = 0;
while (done < nbytes && !feof(buf->infile) && !ferror(buf->infile)) {
off_t len = nbytes - done;
size_t in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
done += fread(byte_buffer, 1, in, buf->infile);
}
return done;
}

void buffer_reset(struct line_buffer *buf)
Expand Down
6 changes: 4 additions & 2 deletions vcs-svn/line_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ int buffer_tmpfile_init(struct line_buffer *buf);
FILE *buffer_tmpfile_rewind(struct line_buffer *buf); /* prepare to write. */
long buffer_tmpfile_prepare_to_read(struct line_buffer *buf);

int buffer_ferror(struct line_buffer *buf);
char *buffer_read_line(struct line_buffer *buf);
char *buffer_read_string(struct line_buffer *buf, uint32_t len);
int buffer_read_char(struct line_buffer *buf);
void buffer_read_binary(struct line_buffer *buf, struct strbuf *sb, uint32_t len);
void buffer_copy_bytes(struct line_buffer *buf, uint32_t len);
void buffer_skip_bytes(struct line_buffer *buf, uint32_t len);
/* Returns number of bytes read (not necessarily written). */
off_t buffer_copy_bytes(struct line_buffer *buf, off_t len);
off_t buffer_skip_bytes(struct line_buffer *buf, off_t len);

#endif
3 changes: 2 additions & 1 deletion vcs-svn/line_buffer.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ Functions

`buffer_skip_bytes`::
Discards `len` bytes from the input stream (stopping early
if necessary because of an error or eof).
if necessary because of an error or eof). Return value is
the number of bytes successfully read.

`buffer_reset`::
Deallocates non-static buffers.
43 changes: 23 additions & 20 deletions vcs-svn/repo_tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ static struct repo_dir *repo_clone_dir(struct repo_dir *orig_dir)
return dir_pointer(new_o);
}

static struct repo_dirent *repo_read_dirent(uint32_t revision, uint32_t *path)
static struct repo_dirent *repo_read_dirent(uint32_t revision,
const uint32_t *path)
{
uint32_t name = 0;
struct repo_dirent *key = dent_pointer(dent_alloc(1));
Expand All @@ -105,7 +106,7 @@ static struct repo_dirent *repo_read_dirent(uint32_t revision, uint32_t *path)
return dent;
}

static void repo_write_dirent(uint32_t *path, uint32_t mode,
static void repo_write_dirent(const uint32_t *path, uint32_t mode,
uint32_t content_offset, uint32_t del)
{
uint32_t name, revision, dir_o = ~0, parent_dir_o = ~0;
Expand Down Expand Up @@ -157,7 +158,24 @@ static void repo_write_dirent(uint32_t *path, uint32_t mode,
dent_remove(&dir_pointer(parent_dir_o)->entries, dent);
}

uint32_t repo_copy(uint32_t revision, uint32_t *src, uint32_t *dst)
uint32_t repo_read_path(const uint32_t *path)
{
uint32_t content_offset = 0;
struct repo_dirent *dent = repo_read_dirent(active_commit, path);
if (dent != NULL)
content_offset = dent->content_offset;
return content_offset;
}

uint32_t repo_read_mode(const uint32_t *path)
{
struct repo_dirent *dent = repo_read_dirent(active_commit, path);
if (dent == NULL)
die("invalid dump: path to be modified is missing");
return dent->mode;
}

void repo_copy(uint32_t revision, const uint32_t *src, const uint32_t *dst)
{
uint32_t mode = 0, content_offset = 0;
struct repo_dirent *src_dent;
Expand All @@ -167,28 +185,13 @@ uint32_t repo_copy(uint32_t revision, uint32_t *src, uint32_t *dst)
content_offset = src_dent->content_offset;
repo_write_dirent(dst, mode, content_offset, 0);
}
return mode;
}

void repo_add(uint32_t *path, uint32_t mode, uint32_t blob_mark)
{
repo_write_dirent(path, mode, blob_mark, 0);
}

uint32_t repo_modify_path(uint32_t *path, uint32_t mode, uint32_t blob_mark)
{
struct repo_dirent *src_dent;
src_dent = repo_read_dirent(active_commit, path);
if (!src_dent)
return 0;
if (!blob_mark)
blob_mark = src_dent->content_offset;
if (!mode)
mode = src_dent->mode;
repo_write_dirent(path, mode, blob_mark, 0);
return mode;
}

void repo_delete(uint32_t *path)
{
repo_write_dirent(path, 0, 0, 1);
Expand Down Expand Up @@ -275,8 +278,8 @@ void repo_diff(uint32_t r1, uint32_t r2)
repo_commit_root_dir(commit_pointer(r2)));
}

void repo_commit(uint32_t revision, uint32_t author, char *log, uint32_t uuid,
uint32_t url, unsigned long timestamp)
void repo_commit(uint32_t revision, const char *author, char *log,
const char *uuid, const char *url, unsigned long timestamp)
{
fast_export_commit(revision, author, log, uuid, url, timestamp);
dent_commit();
Expand Down
10 changes: 6 additions & 4 deletions vcs-svn/repo_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
#define REPO_MAX_PATH_DEPTH 1000

uint32_t next_blob_mark(void);
uint32_t repo_copy(uint32_t revision, uint32_t *src, uint32_t *dst);
void repo_copy(uint32_t revision, const uint32_t *src, const uint32_t *dst);
void repo_add(uint32_t *path, uint32_t mode, uint32_t blob_mark);
uint32_t repo_modify_path(uint32_t *path, uint32_t mode, uint32_t blob_mark);
uint32_t repo_read_path(const uint32_t *path);
uint32_t repo_read_mode(const uint32_t *path);
void repo_delete(uint32_t *path);
void repo_commit(uint32_t revision, uint32_t author, char *log, uint32_t uuid,
uint32_t url, long unsigned timestamp);
void repo_commit(uint32_t revision, const char *author,
char *log, const char *uuid, const char *url,
long unsigned timestamp);
void repo_diff(uint32_t r1, uint32_t r2);
void repo_init(void);
void repo_reset(void);
Expand Down
Loading

0 comments on commit 785d698

Please sign in to comment.