s...@apache.org wrote on Sat, Jun 04, 2011 at 12:32:28 -0000: > Author: stsp > Date: Sat Jun 4 12:32:27 2011 > New Revision: 1131383 > > URL: http://svn.apache.org/viewvc?rev=1131383&view=rev > Log: > Wrap libmagic support in a private API and use this API from libsvn_client. > > This moves all the #ifdef HAVE_LIBMAGIC spaghetti into a single file. > It also makes Subversion's use of libmagic more efficient for recursive > operations because the magic database is only loaded once per invocation > of svn_client_add() and svn_client_import(), not per every invocation of > svn_io_detect_mimetype(). > > Inspired by: hwright > > * subversion/include/private/svn_magic.h: New. > > * subversion/libsvn_subr/magic.c: New. > > * subversion/libsvn_subr/io.c > (svn_io_detect_mimetype2): Drop libmagic support from this function. > > * subversion/libsvn_client/add.c > (svn_client__get_auto_props): Add a MAGIC_COOKIE parameter for use with > the new svn_magic API. Let mime-types obtained from libmagic override > the mimetypes map if the map returned "application/octet-stream" (but > do not override "application/octet-stream" configured via auto-props). > (add_file, add_dir_recursive): Add MAGIC_COOKIE parameter. > (add): Initialise libmagic and pass the magic cookie on to other functions. > > * subversion/libsvn_client/commit.c > (import_ctx): Add a MAGIC_COOKIE here, too. > (import_file): Pass CTX->MAGIC_COOKIE to svn_client__get_auto_props(). > (import): Initialise libmagic and store the cookie in the import context. > > * subversion/libsvn_client/client.h > (svn_client__get_auto_props): Update declaration. > > Added: > subversion/trunk/subversion/include/private/svn_magic.h > subversion/trunk/subversion/libsvn_subr/magic.c > Modified: > subversion/trunk/subversion/libsvn_client/add.c > subversion/trunk/subversion/libsvn_client/client.h > subversion/trunk/subversion/libsvn_client/commit.c > subversion/trunk/subversion/libsvn_subr/io.c > > Added: subversion/trunk/subversion/include/private/svn_magic.h > URL: > http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_magic.h?rev=1131383&view=auto > ============================================================================== > --- subversion/trunk/subversion/include/private/svn_magic.h (added) > +++ subversion/trunk/subversion/include/private/svn_magic.h Sat Jun 4 > 12:32:27 2011 > @@ -0,0 +1,55 @@ > +/** > + * @copyright > + * ==================================================================== > + * Licensed to the Apache Software Foundation (ASF) under one > + * or more contributor license agreements. See the NOTICE file > + * distributed with this work for additional information > + * regarding copyright ownership. The ASF licenses this file > + * to you under the Apache License, Version 2.0 (the > + * "License"); you may not use this file except in compliance > + * with the License. You may obtain a copy of the License at > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, > + * software distributed under the License is distributed on an > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY > + * KIND, either express or implied. See the License for the > + * specific language governing permissions and limitations > + * under the License. > + * ==================================================================== > + * @endcopyright > + * > + * @file svn_magic.h > + * @brief Subversion interface to libmagic. > + */ > + > +#ifndef SVN_MAGIC_H > +#define SVN_MAGIC_H > + > +/* An opaque struct that wraps a libmagic cookie. */ > +typedef struct svn_magic__cookie_t svn_magic__cookie_t; > + > +/* This routine initialises libmagic. > + * Upon success new *MAGIC_COOKIE is allocated in RESULT_POOL. > + * On failure *MAGIC_COOKIE is set to NULL. > + * All resources used by libmagic are freed by a cleanup handler > + * installed on RESULT_POOL, i.e. *MAGIC_COOKIE becomes invalid when > + * the pool is cleared! */ > +void > +svn_magic__init(svn_magic__cookie_t **magic_cookie, > + apr_pool_t *result_pool); > + > +/* Detect the mime-type of the file at LOCAL_ABSPATH using MAGIC_COOKIE. > + * If the mime-type is binary return the result in *MIMETYPE. > + * If the file is not a binary file or if its mime-type cannot be determined > + * set *MIMETYPE to NULL. Allocate *MIMETYPE in RESULT_POOL. > + * Use SCRATCH_POOL for temporary allocations. */ > +svn_error_t * > +svn_magic__detect_binary_mimetype(const char **mimetype, > + const char *local_abspath, > + svn_magic__cookie_t *magic_cookie, > + apr_pool_t *result_pool, > + apr_pool_t *scratch_pool); > + > +#endif /* SVN_MAGIC_H */ > > Modified: subversion/trunk/subversion/libsvn_client/add.c > URL: > http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/add.c?rev=1131383&r1=1131382&r2=1131383&view=diff > ============================================================================== > --- subversion/trunk/subversion/libsvn_client/add.c (original) > +++ subversion/trunk/subversion/libsvn_client/add.c Sat Jun 4 12:32:27 2011 > @@ -47,6 +47,7 @@ > > #include "private/svn_client_private.h" > #include "private/svn_wc_private.h" > +#include "private/svn_magic.h" > > #include "svn_private_config.h" > > @@ -220,6 +221,7 @@ svn_error_t * > svn_client__get_auto_props(apr_hash_t **properties, > const char **mimetype, > const char *path, > + svn_magic__cookie_t *magic_cookie, > svn_client_ctx_t *ctx, > apr_pool_t *pool) > { > @@ -254,38 +256,20 @@ svn_client__get_auto_props(apr_hash_t ** > SVN_ERR(svn_io_detect_mimetype2(&autoprops.mimetype, path, > ctx->mimetypes_map, pool)); > > -#ifdef HAVE_LIBMAGIC > - /* We want to set an svn:mime-type property by default only on binary > - * files. So don't set an svn:mime-type property on text files unless > - * their mime-type appears in the map. This preserves behaviour > - * of Subversion releases that did not include libmagic support. > - * In those releases svn_io_detect_mimetype2() returned > - * "application/octet-stream" or NULL unless the type was in the map. > */ > - if (autoprops.mimetype && strncmp(autoprops.mimetype, "text/", 5) == 0) > - { > - if (ctx->mimetypes_map) > - { > - svn_boolean_t type_is_in_map = FALSE; > - apr_hash_index_t *hi; > - > - for (hi = apr_hash_first(pool, ctx->mimetypes_map); > - hi; > - hi = apr_hash_next(hi)) > - { > - const char *type_from_map = svn__apr_hash_index_val(hi); > - if (strcmp(type_from_map, autoprops.mimetype) == 0) > - { > - type_is_in_map = TRUE; > - break; > - } > - } > - if (!type_is_in_map) > - autoprops.mimetype = NULL; > - } > - else > - autoprops.mimetype = NULL; > + /* If we got no mime-type, or if it is "application/octet-stream", > + * try to get the mime-type from libmagic. */ > + if (magic_cookie && > + (!autoprops.mimetype || > + strcmp(autoprops.mimetype, "application/octet-stream") == 0)) > + { > + const char *magic_mimetype; > + > + SVN_ERR(svn_magic__detect_binary_mimetype(&magic_mimetype, > + path, magic_cookie, > + pool, pool)); > + if (magic_mimetype) > + autoprops.mimetype = magic_mimetype; > } > -#endif > > if (autoprops.mimetype) > apr_hash_set(autoprops.properties, SVN_PROP_MIME_TYPE, > @@ -311,6 +295,7 @@ svn_client__get_auto_props(apr_hash_t ** > /* Only call this if the on-disk node kind is a file. */ > static svn_error_t * > add_file(const char *local_abspath, > + svn_magic__cookie_t *magic_cookie, > svn_client_ctx_t *ctx, > apr_pool_t *pool) > { > @@ -331,7 +316,7 @@ add_file(const char *local_abspath, > we open them to estimate file type. > That's why we postpone the add until after this step. */ > SVN_ERR(svn_client__get_auto_props(&properties, &mimetype, local_abspath, > - ctx, pool)); > + magic_cookie, ctx, pool)); > > /* Add the file */ > SVN_ERR(svn_wc_add_from_disk(ctx->wc_ctx, local_abspath, > @@ -402,6 +387,9 @@ add_file(const char *local_abspath, > * Files and directories that match ignore patterns will not be added unless > * NO_IGNORE is TRUE. > * > + * Use MAGIC_COOKIE (which may be NULL) to detect the mime-type of files > + * if necessary. > + * > * If CTX->CANCEL_FUNC is non-null, call it with CTX->CANCEL_BATON to allow > * the user to cancel the operation > */ > @@ -410,6 +398,7 @@ add_dir_recursive(const char *dir_abspat > svn_depth_t depth, > svn_boolean_t force, > svn_boolean_t no_ignore, > + svn_magic__cookie_t *magic_cookie, > svn_client_ctx_t *ctx, > apr_pool_t *scratch_pool) > { > @@ -476,12 +465,13 @@ add_dir_recursive(const char *dir_abspat > depth_below_here = svn_depth_empty; > > SVN_ERR(add_dir_recursive(abspath, depth_below_here, > - force, no_ignore, ctx, iterpool)); > + force, no_ignore, magic_cookie, > + ctx, iterpool)); > } > else if ((dirent->kind == svn_node_file || dirent->special) > && depth >= svn_depth_files) > { > - err = add_file(abspath, ctx, iterpool); > + err = add_file(abspath, magic_cookie, ctx, iterpool); > if (err && err->apr_err == SVN_ERR_ENTRY_EXISTS && force) > svn_error_clear(err); > else > @@ -516,6 +506,9 @@ add(void *baton, apr_pool_t *result_pool > svn_node_kind_t kind; > svn_error_t *err; > struct add_with_write_lock_baton *b = baton; > + svn_magic__cookie_t *magic_cookie; > +
Need to initialize this to NULL, right?