⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 load.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
                            void *cancel_baton,                            apr_pool_t *pool){  svn_boolean_t eof;  svn_stringbuf_t *linebuf;  void *rev_baton = NULL;  char *buffer = apr_palloc(pool, SVN__STREAM_CHUNK_SIZE);  apr_size_t buflen = SVN__STREAM_CHUNK_SIZE;  apr_pool_t *linepool = svn_pool_create(pool);  apr_pool_t *revpool = svn_pool_create(pool);  apr_pool_t *nodepool = svn_pool_create(pool);  int version;  SVN_ERR(svn_stream_readline(stream, &linebuf, "\n", &eof, linepool));  if (eof)    return stream_ran_dry();      /* The first two lines of the stream are the dumpfile-format version     number, and a blank line. */  SVN_ERR(parse_format_version(linebuf->data, &version));  /* If we were called from svn_repos_parse_dumpstream(), the     callbacks to handle delta contents will be NULL, so we have to     reject dumpfiles with the current version. */  if (version == SVN_REPOS_DUMPFILE_FORMAT_VERSION      && (!parse_fns->delete_node_property || !parse_fns->apply_textdelta))    return svn_error_createf(SVN_ERR_STREAM_MALFORMED_DATA, NULL,                             _("Unsupported dumpfile version: %d"), version);  /* A dumpfile "record" is defined to be a header-block of     rfc822-style headers, possibly followed by a content-block.       - A header-block is always terminated by a single blank line (\n\n)       - We know whether the record has a content-block by looking for         a 'Content-length:' header.  The content-block will always be         of a specific length, plus an extra newline.     Once a record is fully sucked from the stream, an indeterminate     number of blank lines (or lines that begin with whitespace) may     follow before the next record (or the end of the stream.)  */    while (1)    {      apr_hash_t *headers;      void *node_baton;      svn_boolean_t found_node = FALSE;      svn_boolean_t old_v1_with_cl = FALSE;      const char *content_length;      const char *prop_cl;      const char *text_cl;      const char *value;      svn_filesize_t actual_prop_length;      /* Clear our per-line pool. */      svn_pool_clear(linepool);      /* Check for cancellation. */      if (cancel_func)        SVN_ERR(cancel_func(cancel_baton));      /* Keep reading blank lines until we discover a new record, or until         the stream runs out. */      SVN_ERR(svn_stream_readline(stream, &linebuf, "\n", &eof, linepool));      if (eof)        {          if (svn_stringbuf_isempty(linebuf))            break;   /* end of stream, go home. */          else            return stream_ran_dry();        }      if ((linebuf->len == 0) || (apr_isspace(linebuf->data[0])))        continue; /* empty line ... loop */      /*** Found the beginning of a new record. ***/       /* The last line we read better be a header of some sort.         Read the whole header-block into a hash. */      SVN_ERR(read_header_block(stream, linebuf, &headers, linepool));      /*** Handle the various header blocks. ***/      /* Is this a revision record? */      if (apr_hash_get(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER,                       APR_HASH_KEY_STRING))        {          /* If we already have a rev_baton open, we need to close it             and clear the per-revision subpool. */          if (rev_baton != NULL)            {              SVN_ERR(parse_fns->close_revision(rev_baton));              svn_pool_clear(revpool);            }          SVN_ERR(parse_fns->new_revision_record(&rev_baton,                                                 headers, parse_baton,                                                 revpool));        }      /* Or is this, perhaps, a node record? */      else if (apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_PATH,                            APR_HASH_KEY_STRING))        {          SVN_ERR(parse_fns->new_node_record(&node_baton,                                             headers,                                             rev_baton,                                             nodepool));          found_node = TRUE;        }      /* Or is this the repos UUID? */      else if ((value = apr_hash_get(headers, SVN_REPOS_DUMPFILE_UUID,                                     APR_HASH_KEY_STRING)))        {          SVN_ERR(parse_fns->uuid_record(value, parse_baton, pool));        }      /* Or perhaps a dumpfile format? */      else if ((value = apr_hash_get(headers,                                      SVN_REPOS_DUMPFILE_MAGIC_HEADER,                                     APR_HASH_KEY_STRING)))        {          /* ### someday, switch modes of operation here. */          version = atoi(value);        }      /* Or is this bogosity?! */      else        {          /* What the heck is this record?!? */          return svn_error_create(SVN_ERR_STREAM_MALFORMED_DATA, NULL,                                  _("Unrecognized record type in stream"));        }      /* Need 3 values below to determine v1 dump type         Old (pre 0.14?) v1 dumps don't have Prop-content-length         and Text-content-length fields, but always have a properties         block in a block with Content-Length > 0 */      content_length = apr_hash_get(headers,                                    SVN_REPOS_DUMPFILE_CONTENT_LENGTH,                                    APR_HASH_KEY_STRING);      prop_cl = apr_hash_get(headers,                             SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH,                             APR_HASH_KEY_STRING);      text_cl = apr_hash_get(headers,                             SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH,                             APR_HASH_KEY_STRING);      old_v1_with_cl =        version == 1 && content_length && ! prop_cl && ! text_cl;      /* Is there a props content-block to parse? */      if (prop_cl || old_v1_with_cl)        {          const char *delta = apr_hash_get(headers,                                           SVN_REPOS_DUMPFILE_PROP_DELTA,                                           APR_HASH_KEY_STRING);          svn_boolean_t is_delta = (delta && strcmp(delta, "true") == 0);          /* First, remove all node properties, unless this is a delta             property block. */          if (found_node && !is_delta)            SVN_ERR(parse_fns->remove_node_props(node_baton));          SVN_ERR(parse_property_block                  (stream,                   svn__atoui64(prop_cl ? prop_cl : content_length),                   parse_fns,                   found_node ? node_baton : rev_baton,                   found_node,                   &actual_prop_length,                   found_node ? nodepool : revpool));        }      /* Is there a text content-block to parse? */      if (text_cl)        {          const char *delta = apr_hash_get(headers,                                           SVN_REPOS_DUMPFILE_TEXT_DELTA,                                           APR_HASH_KEY_STRING);          svn_boolean_t is_delta = (delta && strcmp(delta, "true") == 0);          SVN_ERR(parse_text_block(stream,                                   svn__atoui64(text_cl),                                   is_delta,                                   parse_fns,                                   found_node ? node_baton : rev_baton,                                   buffer,                                   buflen,                                   found_node ? nodepool : revpool));        }      else if (old_v1_with_cl)        {          /* An old-v1 block with a Content-length might have a text block.             If the property block did not consume all the bytes of the             Content-length, then it clearly does have a text block.             If not, then we must deduce whether we have an *empty* text             block or an *absent* text block.  The rules are:             - "Node-kind: file" blocks have an empty (i.e. present, but               zero-length) text block, since they represent a file               modification.  Note that file-copied-text-unmodified blocks               have no Content-length - even if they should have contained               a modified property block, the pre-0.14 dumper forgets to               dump the modified properties.              - If it is not a file node, then it is a revision or directory,               and so has an absent text block.          */          const char *node_kind;          svn_filesize_t cl_value = svn__atoui64(content_length)                                    - actual_prop_length;          if (cl_value ||               ((node_kind = apr_hash_get(headers,                                         SVN_REPOS_DUMPFILE_NODE_KIND,                                         APR_HASH_KEY_STRING))               && strcmp(node_kind, "file") == 0)             )            SVN_ERR(parse_text_block(stream,                                     cl_value,                                     FALSE,                                     parse_fns,                                     found_node ? node_baton : rev_baton,                                     buffer,                                     buflen,                                     found_node ? nodepool : revpool));        }      /* if we have a content-length header, did we read all of it?         in case of an old v1, we *always* read all of it, because         text-content-length == content-length - prop-content-length      */      if (content_length && ! old_v1_with_cl)        {          apr_size_t rlen, num_to_read;          svn_filesize_t remaining =            svn__atoui64(content_length) -            (prop_cl ? svn__atoui64(prop_cl) : 0) -            (text_cl ? svn__atoui64(text_cl) : 0);          if (remaining < 0)            return svn_error_create(SVN_ERR_STREAM_MALFORMED_DATA, NULL,                                    _("Sum of subblock sizes larger than "                                      "total block content length"));          /* Consume remaining bytes in this content block */          while (remaining > 0)            {              if (remaining >= buflen)                rlen = buflen;              else                rlen = (apr_size_t) remaining;              num_to_read = rlen;              SVN_ERR(svn_stream_read(stream, buffer, &rlen));              remaining -= rlen;              if (rlen != num_to_read)                return stream_ran_dry();            }        }      /* If we just finished processing a node record, we need to         close the node record and clear the per-node subpool. */      if (found_node)        {          SVN_ERR(parse_fns->close_node(node_baton));          svn_pool_clear(nodepool);        }            /*** End of processing for one record. ***/    } /* end of stream */  /* Close out whatever revision we're in. */  if (rev_baton != NULL)    SVN_ERR(parse_fns->close_revision(rev_baton));  svn_pool_destroy(linepool);  svn_pool_destroy(revpool);  svn_pool_destroy(nodepool);  return SVN_NO_ERROR;}svn_error_t *svn_repos_parse_dumpstream(svn_stream_t *stream,                           const svn_repos_parser_fns_t *parse_fns,                           void *parse_baton,                           svn_cancel_func_t cancel_func,                           void *cancel_baton,                           apr_pool_t *pool){  svn_repos_parse_fns2_t *fns2 = fns2_from_fns(parse_fns, pool);  return svn_repos_parse_dumpstream2(stream, fns2, parse_baton,                                     cancel_func, cancel_baton, pool);}/*----------------------------------------------------------------------*//** vtable for doing commits to a fs **/static struct node_baton *make_node_baton(apr_hash_t *headers,                struct revision_baton *rb,                apr_pool_t *pool){  struct node_baton *nb = apr_pcalloc(pool, sizeof(*nb));  const char *val;  /* Start with sensible defaults. */  nb->rb = rb;  nb->pool = pool;  nb->kind = svn_node_unknown;  /* Then add info from the headers.  */  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_PATH,                          APR_HASH_KEY_STRING)))  {    if (rb->pb->parent_dir)      nb->path = svn_path_join(rb->pb->parent_dir, val, pool);    else      nb->path = apr_pstrdup(pool, val);  }  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_KIND,                          APR_HASH_KEY_STRING)))    {      if (! strcmp(val, "file"))        nb->kind = svn_node_file;      else if (! strcmp(val, "dir"))        nb->kind = svn_node_dir;    }  nb->action = (enum svn_node_action)(-1);  /* an invalid action code */  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_ACTION,                          APR_HASH_KEY_STRING)))    {      if (! strcmp(val, "change"))        nb->action = svn_node_action_change;      else if (! strcmp(val, "add"))        nb->action = svn_node_action_add;      else if (! strcmp(val, "delete"))        nb->action = svn_node_action_delete;      else if (! strcmp(val, "replace"))        nb->action = svn_node_action_replace;    }  nb->copyfrom_rev = SVN_INVALID_REVNUM;  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV,                          APR_HASH_KEY_STRING)))    {      nb->copyfrom_rev = (svn_revnum_t) atoi(val);    }  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH,                          APR_HASH_KEY_STRING)))    {      if (rb->pb->parent_dir)        nb->copyfrom_path = svn_path_join(rb->pb->parent_dir,                                          (*val == '/' ? val + 1 : val), pool);      else        nb->copyfrom_path = apr_pstrdup(pool, val);    }  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_CHECKSUM,                          APR_HASH_KEY_STRING)))    {      nb->md5_checksum = apr_pstrdup(pool, val);    }  /* What's cool about this dump format is that the parser just     ignores any unrecognized headers.  :-)  */  return nb;}static struct revision_baton *make_revision_baton(apr_hash_t *headers,                    struct parse_baton *pb,                    apr_pool_t *pool){  struct revision_baton *rb = apr_pcalloc(pool, sizeof(*rb));  const char *val;  rb->pb = pb;  rb->pool = pool;  rb->rev = SVN_INVALID_REVNUM;  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER,                          APR_HASH_KEY_STRING)))    rb->rev = SVN_STR_TO_REV(val);  return rb;}static svn_error_t *new_revision_record(void **revision_baton,                    apr_hash_t *headers,                    void *parse_baton,                    apr_pool_t *pool){  struct parse_baton *pb = parse_baton;  struct revision_baton *rb;  svn_revnum_t head_rev;  rb = make_revision_baton(headers, pb, pool);  SVN_ERR(svn_fs_youngest_rev(&head_rev, pb->fs, pool));  /* FIXME: This is a lame fallback loading multiple segments of dump in     several seperate operations. It is highly susceptible to race conditions.     Calculate the revision 'offset' for finding copyfrom sources.     It might be positive or negative. */  rb->rev_offset = (rb->rev) - (head_rev + 1);   if (rb->rev > 0)    {      /* Create a new fs txn. */      SVN_ERR(svn_fs_begin_txn2(&(rb->txn), pb->fs, head_rev, 0, pool));      SVN_ERR(svn_fs_txn_root(&(rb->txn_root), rb->txn, pool));            SVN_ERR(svn_stream_printf(pb->outstream, pool,                                _("<<< Started new transaction, based on "                                  "original revision %ld\n"), rb->rev));    }  /* If we're parsing revision 0, only the revision are (possibly)     interesting to us: when loading the stream into an empty     filesystem, then we want new filesystem's revision 0 to have the     same props.  Otherwise, we just ignore revision 0 in the stream. */    *revision_baton = rb;  return SVN_NO_ERROR;}/* Factorized helper func for new_node_record() */static svn_error_t *maybe_add_with_history(struct node_baton *nb,                       struct revision_baton *rb,                       apr_pool_t *pool){  struct parse_baton *pb = rb->pb;  apr_size_t len;  if ((nb->copyfrom_path == NULL) || (! pb->use_history))    {      /* Add empty file or dir, without history. */      if (nb->kind == svn_node_file)        SVN_ERR(svn_fs_make_file(rb->txn_root, nb->path, pool));      else if (nb->kind == svn_node_dir)        SVN_ERR(svn_fs_make_dir(rb->txn_root, nb->path, pool));    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -