Code

Merge branch 'db/length-as-hash' (early part) into db/svn-fe-code-purge
authorJonathan Nieder <jrnieder@gmail.com>
Tue, 22 Mar 2011 23:11:59 +0000 (18:11 -0500)
committerJonathan Nieder <jrnieder@gmail.com>
Tue, 22 Mar 2011 23:11:59 +0000 (18:11 -0500)
* 'db/length-as-hash' (early part):
  vcs-svn: implement perfect hash for top-level keys
  vcs-svn: implement perfect hash for node-prop keys
  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

Conflicts:
vcs-svn/fast_export.c
vcs-svn/svndump.c

1  2 
vcs-svn/fast_export.c
vcs-svn/svndump.c

index f19db9ae8274e530250189d138616e18fbb071ba,07a8353c8bfaa4d320a5c2fa073d08aaaebdc5e6..32f0c8cfcc98ad3104ee9eca01ce98909bcbfff8
@@@ -93,97 -63,23 +93,106 @@@ void fast_export_end_commit(uint32_t re
        printf("progress Imported commit %"PRIu32".\n\n", revision);
  }
  
 -void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len, struct line_buffer *input)
 +static void ls_from_rev(uint32_t rev, uint32_t depth, const uint32_t *path)
 +{
 +      /* ls :5 path/to/old/file */
 +      printf("ls :%"PRIu32" \"", rev);
 +      pool_print_seq_q(depth, path, '/', stdout);
 +      printf("\"\n");
 +      fflush(stdout);
 +}
 +
 +static void ls_from_active_commit(uint32_t depth, const uint32_t *path)
 +{
 +      /* ls "path/to/file" */
 +      printf("ls \"");
 +      pool_print_seq_q(depth, path, '/', stdout);
 +      printf("\"\n");
 +      fflush(stdout);
 +}
 +
 +static const char *get_response_line(void)
 +{
 +      const char *line = buffer_read_line(&report_buffer);
 +      if (line)
 +              return line;
 +      if (buffer_ferror(&report_buffer))
 +              die_errno("error reading from fast-import");
 +      die("unexpected end of fast-import feedback");
 +}
 +
+ 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_data(uint32_t mode, 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);
 +      printf("data %"PRIu32"\n", len);
-       buffer_copy_bytes(input, len);
+       if (buffer_copy_bytes(input, len) != len)
+               die_short_read(input);
        fputc('\n', stdout);
  }
 +
 +static int parse_ls_response(const char *response, uint32_t *mode,
 +                                      struct strbuf *dataref)
 +{
 +      const char *tab;
 +      const char *response_end;
 +
 +      assert(response);
 +      response_end = response + strlen(response);
 +
 +      if (*response == 'm') { /* Missing. */
 +              errno = ENOENT;
 +              return -1;
 +      }
 +
 +      /* Mode. */
 +      if (response_end - response < strlen("100644") ||
 +          response[strlen("100644")] != ' ')
 +              die("invalid ls response: missing mode: %s", response);
 +      *mode = 0;
 +      for (; *response != ' '; response++) {
 +              char ch = *response;
 +              if (ch < '0' || ch > '7')
 +                      die("invalid ls response: mode is not octal: %s", response);
 +              *mode *= 8;
 +              *mode += ch - '0';
 +      }
 +
 +      /* ' blob ' or ' tree ' */
 +      if (response_end - response < strlen(" blob ") ||
 +          (response[1] != 'b' && response[1] != 't'))
 +              die("unexpected ls response: not a tree or blob: %s", response);
 +      response += strlen(" blob ");
 +
 +      /* Dataref. */
 +      tab = memchr(response, '\t', response_end - response);
 +      if (!tab)
 +              die("invalid ls response: missing tab: %s", response);
 +      strbuf_add(dataref, response, tab - response);
 +      return 0;
 +}
 +
 +int fast_export_ls_rev(uint32_t rev, uint32_t depth, const uint32_t *path,
 +                              uint32_t *mode, struct strbuf *dataref)
 +{
 +      ls_from_rev(rev, depth, path);
 +      return parse_ls_response(get_response_line(), mode, dataref);
 +}
 +
 +int fast_export_ls(uint32_t depth, const uint32_t *path,
 +                              uint32_t *mode, struct strbuf *dataref)
 +{
 +      ls_from_active_commit(depth, path);
 +      return parse_ls_response(get_response_line(), mode, dataref);
 +}
index 7ecb227a6d62abd2031de44af646b19bc9fcf539,77680a31e8fed797715bc7c6727082574951ad0c..ff985fe9e69f10f17918ee72cd49c0e07b96f132
  #include "obj_pool.h"
  #include "string_pool.h"
  
 +#define REPORT_FILENO 3
 +
+ /*
+  * Compare start of string to literal of equal length;
+  * must be guarded by length test.
+  */
+ #define constcmp(s, ref) memcmp(s, ref, sizeof(ref) - 1)
  #define NODEACT_REPLACE 4
  #define NODEACT_DELETE 3
  #define NODEACT_ADD 2
@@@ -329,25 -311,34 +344,38 @@@ void svndump_read(const char *url
                        if (dump_ctx.version > 3)
                                die("expected svn dump format version <= 3, found %"PRIu32,
                                    dump_ctx.version);
-               } else if (key == keys.uuid) {
+                       break;
+               case sizeof("UUID"):
+                       if (constcmp(t, "UUID"))
+                               continue;
                        dump_ctx.uuid = pool_intern(val);
-               } else if (key == keys.revision_number) {
+                       break;
+               case sizeof("Revision-number"):
+                       if (constcmp(t, "Revision-number"))
+                               continue;
                        if (active_ctx == NODE_CTX)
                                handle_node();
 +                      if (active_ctx == REV_CTX)
 +                              begin_revision();
                        if (active_ctx != DUMP_CTX)
 -                              handle_revision();
 +                              end_revision();
                        active_ctx = REV_CTX;
                        reset_rev_ctx(atoi(val));
-               } else if (key == keys.node_path) {
-                       if (active_ctx == NODE_CTX)
-                               handle_node();
-                       if (active_ctx == REV_CTX)
-                               begin_revision();
-                       active_ctx = NODE_CTX;
-                       reset_node_ctx(val);
-               } else if (key == keys.node_kind) {
+                       break;
+               case sizeof("Node-path"):
+                       if (prefixcmp(t, "Node-"))
+                               continue;
+                       if (!constcmp(t + strlen("Node-"), "path")) {
+                               if (active_ctx == NODE_CTX)
+                                       handle_node();
++                              if (active_ctx == REV_CTX)
++                                      begin_revision();
+                               active_ctx = NODE_CTX;
+                               reset_node_ctx(val);
+                               break;
+                       }
+                       if (constcmp(t + strlen("Node-"), "kind"))
+                               continue;
                        if (!strcmp(val, "dir"))
                                node_ctx.type = REPO_MODE_DIR;
                        else if (!strcmp(val, "file"))
                                read_props();
                        } else if (active_ctx == NODE_CTX) {
                                handle_node();
 -                              active_ctx = REV_CTX;
 +                              active_ctx = INTERNODE_CTX;
                        } else {
                                fprintf(stderr, "Unexpected content length header: %"PRIu32"\n", len);
-                               buffer_skip_bytes(&input, len);
+                               if (buffer_skip_bytes(&input, len) != len)
+                                       die_short_read();
                        }
                }
        }
+       if (buffer_ferror(&input))
+               die_short_read();
        if (active_ctx == NODE_CTX)
                handle_node();
 +      if (active_ctx == REV_CTX)
 +              begin_revision();
        if (active_ctx != DUMP_CTX)
 -              handle_revision();
 +              end_revision();
  }
  
  int svndump_init(const char *filename)