📄 add.c
字号:
/*
* add.c: wrappers around wc add/mkdir functionality.
*
* ====================================================================
* Copyright (c) 2000-2004 CollabNet. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://subversion.tigris.org/license-1.html.
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
*
* This software consists of voluntary contributions made by many
* individuals. For exact contribution history, see the revision
* history and logs, available at http://subversion.tigris.org/.
* ====================================================================
*/
/* ==================================================================== */
/*** Includes. ***/
#include <string.h>
#include <apr_lib.h>
#include <apr_fnmatch.h>
#include "svn_wc.h"
#include "svn_client.h"
#include "svn_string.h"
#include "svn_pools.h"
#include "svn_error.h"
#include "svn_path.h"
#include "svn_io.h"
#include "svn_config.h"
#include "client.h"
#include "svn_private_config.h"
/*** Code. ***/
/* This structure is used as baton for enumerating the config entries
in the auto-props section.
*/
typedef struct
{
/* the file name for which properties are searched */
const char *filename;
/* when this flag is set the hash contains svn:executable */
svn_boolean_t have_executable;
/* when mimetype is not NULL is set the hash contains svn:mime-type */
const char *mimetype;
/* the hash table for storing the property name/value pairs */
apr_hash_t *properties;
/* a pool used for allocating memory */
apr_pool_t *pool;
} auto_props_baton_t;
/* Remove leading and trailing white space from a C string, in place. */
static void
trim_string (char **pstr)
{
char *str = *pstr;
int i;
while (apr_isspace (*str))
str++;
*pstr = str;
i = strlen (str);
while ((i > 0) && apr_isspace (str[i-1]))
i--;
str[i] = '\0';
}
/* For one auto-props config entry (NAME, VALUE), if the filename pattern
NAME matches BATON->filename then add the properties listed in VALUE
into BATON->properties. BATON must point to an auto_props_baton_t.
*/
static svn_boolean_t
auto_props_enumerator (const char *name,
const char *value,
void *baton)
{
auto_props_baton_t *autoprops = baton;
char *property;
char *last_token;
int len;
/* nothing to do here without a value */
if (strlen (value) == 0)
return TRUE;
/* check if filename matches and return if it doesn't */
if (apr_fnmatch (name, autoprops->filename, 0) == APR_FNM_NOMATCH)
return TRUE;
/* parse the value (we dup it first to effectively lose the
'const', and to avoid messing up the original value) */
property = apr_pstrdup (autoprops->pool, value);
property = apr_strtok (property, ";", &last_token);
while (property)
{
char *this_value;
this_value = strchr (property, '=');
if (this_value)
{
*this_value = '\0';
this_value++;
trim_string (&this_value);
}
else
{
this_value = (char *)"";
}
trim_string (&property);
len = strlen (property);
if (len > 0)
{
svn_string_t *propval = apr_pcalloc (autoprops->pool,
sizeof (*propval));
propval->data = this_value;
propval->len = strlen (this_value);
apr_hash_set (autoprops->properties, property, len, propval);
if (strcmp (property, SVN_PROP_MIME_TYPE) == 0)
autoprops->mimetype = this_value;
else if (strcmp (property, SVN_PROP_EXECUTABLE) == 0)
autoprops->have_executable = TRUE;
}
property = apr_strtok (NULL, ";", &last_token);
}
return TRUE;
}
svn_error_t *
svn_client__get_auto_props (apr_hash_t **properties,
const char **mimetype,
const char *path,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
svn_config_t *cfg;
svn_boolean_t use_autoprops;
auto_props_baton_t autoprops;
/* initialisation */
autoprops.properties = apr_hash_make (pool);
autoprops.filename = svn_path_basename (path, pool);
autoprops.pool = pool;
autoprops.mimetype = NULL;
autoprops.have_executable = FALSE;
*properties = autoprops.properties;
cfg = ctx->config ? apr_hash_get (ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
APR_HASH_KEY_STRING) : NULL;
/* check that auto props is enabled */
SVN_ERR (svn_config_get_bool (cfg, &use_autoprops,
SVN_CONFIG_SECTION_MISCELLANY,
SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS, FALSE));
/* search for auto props */
if (use_autoprops)
svn_config_enumerate (cfg, SVN_CONFIG_SECTION_AUTO_PROPS,
auto_props_enumerator, &autoprops);
/* if mimetype has not been set check the file */
if (! autoprops.mimetype)
{
SVN_ERR (svn_io_detect_mimetype (&autoprops.mimetype, path, pool));
if (autoprops.mimetype)
apr_hash_set (autoprops.properties, SVN_PROP_MIME_TYPE,
strlen (SVN_PROP_MIME_TYPE),
svn_string_create (autoprops.mimetype, pool));
}
/* if executable has not been set check the file */
if (! autoprops.have_executable)
{
svn_boolean_t executable = FALSE;
SVN_ERR (svn_io_is_file_executable (&executable, path, pool));
if (executable)
apr_hash_set (autoprops.properties, SVN_PROP_EXECUTABLE,
strlen (SVN_PROP_EXECUTABLE),
svn_string_create ("", pool));
}
*mimetype = autoprops.mimetype;
return SVN_NO_ERROR;
}
static svn_error_t *
add_file (const char *path,
svn_client_ctx_t *ctx,
svn_wc_adm_access_t *adm_access,
apr_pool_t *pool)
{
apr_hash_t* properties;
apr_hash_index_t *hi;
const char *mimetype;
svn_node_kind_t kind;
svn_boolean_t is_special;
/* add the file */
SVN_ERR (svn_wc_add (path, adm_access, NULL, SVN_INVALID_REVNUM,
ctx->cancel_func, ctx->cancel_baton,
NULL, NULL, pool));
/* Check to see if this is a special file. */
SVN_ERR (svn_io_check_special_path (path, &kind, &is_special, pool));
if (is_special)
{
/* This must be a special file. */
SVN_ERR (svn_wc_prop_set (SVN_PROP_SPECIAL,
svn_string_create (SVN_PROP_SPECIAL_VALUE, pool),
path, adm_access, pool));
mimetype = NULL;
}
else
{
/* get automatic properties */
SVN_ERR (svn_client__get_auto_props (&properties, &mimetype, path, ctx,
pool));
if (properties)
{
/* loop through the hashtable and add the properties */
for (hi = apr_hash_first (pool, properties);
hi != NULL; hi = apr_hash_next (hi))
{
const void *pname;
void *pval;
apr_hash_this (hi, &pname, NULL, &pval);
SVN_ERR (svn_wc_prop_set (pname, pval, path, adm_access, pool));
}
}
}
/* Report the addition to the caller. */
if (ctx->notify_func != NULL)
(*ctx->notify_func) (ctx->notify_baton, path, svn_wc_notify_add,
svn_node_file,
mimetype,
svn_wc_notify_state_unknown,
svn_wc_notify_state_unknown,
SVN_INVALID_REVNUM);
return SVN_NO_ERROR;
}
static svn_error_t *
add_dir_recursive (const char *dirname,
svn_wc_adm_access_t *adm_access,
svn_boolean_t force,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
apr_dir_t *dir;
apr_finfo_t this_entry;
svn_error_t *err;
apr_pool_t *subpool;
apr_int32_t flags = APR_FINFO_TYPE | APR_FINFO_NAME;
svn_wc_adm_access_t *dir_access;
apr_array_header_t *ignores;
/* Check cancellation; note that this catches recursive calls too. */
if (ctx->cancel_func)
SVN_ERR (ctx->cancel_func (ctx->cancel_baton));
/* Add this directory to revision control. */
err = svn_wc_add (dirname, adm_access,
NULL, SVN_INVALID_REVNUM,
ctx->cancel_func, ctx->cancel_baton,
ctx->notify_func, ctx->notify_baton, pool);
if (err && err->apr_err == SVN_ERR_ENTRY_EXISTS && force)
svn_error_clear (err);
else if (err)
return err;
SVN_ERR (svn_wc_adm_retrieve (&dir_access, adm_access, dirname, pool));
SVN_ERR (svn_wc_get_default_ignores (&ignores, ctx->config, pool));
/* Create a subpool for iterative memory control. */
subpool = svn_pool_create (pool);
/* Read the directory entries one by one and add those things to
revision control. */
SVN_ERR (svn_io_dir_open (&dir, dirname, pool));
for (err = svn_io_dir_read (&this_entry, flags, dir, subpool);
err == SVN_NO_ERROR;
err = svn_io_dir_read (&this_entry, flags, dir, subpool))
{
const char *fullpath;
/* Check cancellation so you can cancel during an
* add of a directory with lots of files. */
if (ctx->cancel_func)
SVN_ERR (ctx->cancel_func (ctx->cancel_baton));
/* Skip over SVN admin directories. */
if (strcmp (this_entry.name, SVN_WC_ADM_DIR_NAME) == 0)
continue;
/* Skip entries for this dir and its parent. */
if (this_entry.name[0] == '.'
&& (this_entry.name[1] == '\0'
|| (this_entry.name[1] == '.' && this_entry.name[2] == '\0')))
continue;
if (svn_cstring_match_glob_list (this_entry.name, ignores))
continue;
/* Construct the full path of the entry. */
fullpath = svn_path_join (dirname, this_entry.name, subpool);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -