Skip to content

Commit

Permalink
Merge pull request #844 from arrbee/init-extended
Browse files Browse the repository at this point in the history
Add git_repository_init_ext for power initters
  • Loading branch information
Vicent Martí committed Aug 23, 2012
2 parents 5fdc41e + e9ca852 commit c920e16
Show file tree
Hide file tree
Showing 38 changed files with 1,922 additions and 276 deletions.
9 changes: 5 additions & 4 deletions include/git2/config.h
Expand Up @@ -80,15 +80,16 @@ GIT_EXTERN(int) git_config_find_global(char *global_config_path, size_t length);
GIT_EXTERN(int) git_config_find_system(char *system_config_path, size_t length);

/**
* Open the global configuration file
* Open the global and system configuration files
*
* Utility wrapper that calls `git_config_find_global`
* and opens the located file, if it exists.
* Utility wrapper that finds the global and system configuration files
* and opens them into a single prioritized config object that can be
* used when accessing default config data outside a repository.
*
* @param out Pointer to store the config instance
* @return 0 or an error code
*/
GIT_EXTERN(int) git_config_open_global(git_config **out);
GIT_EXTERN(int) git_config_open_default(git_config **out);

/**
* Create a configuration file backend for ondisk files
Expand Down
153 changes: 149 additions & 4 deletions include/git2/repository.h
Expand Up @@ -83,13 +83,39 @@ GIT_EXTERN(int) git_repository_discover(
int across_fs,
const char *ceiling_dirs);

/**
* Option flags for `git_repository_open_ext`.
*
* * GIT_REPOSITORY_OPEN_NO_SEARCH - Only open the repository if it can be
* immediately found in the start_path. Do not walk up from the
* start_path looking at parent directories.
* * GIT_REPOSITORY_OPEN_CROSS_FS - Unless this flag is set, open will not
* continue searching across filesystem boundaries (i.e. when `st_dev`
* changes from the `stat` system call). (E.g. Searching in a user's home
* directory "/home/user/source/" will not return "/.git/" as the found
* repo if "/" is a different filesystem than "/home".)
*/
enum {
GIT_REPOSITORY_OPEN_NO_SEARCH = (1 << 0),
GIT_REPOSITORY_OPEN_CROSS_FS = (1 << 1),
};

/**
* Find and open a repository with extended controls.
*
* @param repo_out Pointer to the repo which will be opened. This can
* actually be NULL if you only want to use the error code to
* see if a repo at this path could be opened.
* @param start_path Path to open as git repository. If the flags
* permit "searching", then this can be a path to a subdirectory
* inside the working directory of the repository.
* @param flags A combination of the GIT_REPOSITORY_OPEN flags above.
* @param ceiling_dirs A GIT_PATH_LIST_SEPARATOR delimited list of path
* prefixes at which the search for a containing repository should
* terminate.
* @return 0 on success, GIT_ENOTFOUND if no repository could be found,
* or -1 if there was a repository but open failed for some reason
* (such as repo corruption or system errors).
*/
GIT_EXTERN(int) git_repository_open_ext(
git_repository **repo,
Expand Down Expand Up @@ -118,13 +144,127 @@ GIT_EXTERN(void) git_repository_free(git_repository *repo);
*
* @param repo_out pointer to the repo which will be created or reinitialized
* @param path the path to the repository
* @param is_bare if true, a Git repository without a working directory is created
* at the pointed path. If false, provided path will be considered as the working
* directory into which the .git directory will be created.
* @param is_bare if true, a Git repository without a working directory is
* created at the pointed path. If false, provided path will be
* considered as the working directory into which the .git directory
* will be created.
*
* @return 0 or an error code
*/
GIT_EXTERN(int) git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare);
GIT_EXTERN(int) git_repository_init(
git_repository **repo_out,
const char *path,
unsigned is_bare);

/**
* Option flags for `git_repository_init_ext`.
*
* These flags configure extra behaviors to `git_repository_init_ext`.
* In every case, the default behavior is the zero value (i.e. flag is
* not set). Just OR the flag values together for the `flags` parameter
* when initializing a new repo. Details of individual values are:
*
* * BARE - Create a bare repository with no working directory.
* * NO_REINIT - Return an EEXISTS error if the repo_path appears to
* already be an git repository.
* * NO_DOTGIT_DIR - Normally a "/.git/" will be appended to the repo
* path for non-bare repos (if it is not already there), but
* passing this flag prevents that behavior.
* * MKDIR - Make the repo_path (and workdir_path) as needed. Init is
* always willing to create the ".git" directory even without this
* flag. This flag tells init to create the trailing component of
* the repo and workdir paths as needed.
* * MKPATH - Recursively make all components of the repo and workdir
* paths as necessary.
* * EXTERNAL_TEMPLATE - libgit2 normally uses internal templates to
* initialize a new repo. This flags enables external templates,
* looking the "template_path" from the options if set, or the
* `init.templatedir` global config if not, or falling back on
* "/usr/share/git-core/templates" if it exists.
*/
enum {
GIT_REPOSITORY_INIT_BARE = (1u << 0),
GIT_REPOSITORY_INIT_NO_REINIT = (1u << 1),
GIT_REPOSITORY_INIT_NO_DOTGIT_DIR = (1u << 2),
GIT_REPOSITORY_INIT_MKDIR = (1u << 3),
GIT_REPOSITORY_INIT_MKPATH = (1u << 4),
GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE = (1u << 5),
};

/**
* Mode options for `git_repository_init_ext`.
*
* Set the mode field of the `git_repository_init_options` structure
* either to the custom mode that you would like, or to one of the
* following modes:
*
* * SHARED_UMASK - Use permissions configured by umask - the default.
* * SHARED_GROUP - Use "--shared=group" behavior, chmod'ing the new repo
* to be group writable and "g+sx" for sticky group assignment.
* * SHARED_ALL - Use "--shared=all" behavior, adding world readability.
* * Anything else - Set to custom value.
*/
enum {
GIT_REPOSITORY_INIT_SHARED_UMASK = 0,
GIT_REPOSITORY_INIT_SHARED_GROUP = 0002775,
GIT_REPOSITORY_INIT_SHARED_ALL = 0002777,
};

/**
* Extended options structure for `git_repository_init_ext`.
*
* This contains extra options for `git_repository_init_ext` that enable
* additional initialization features. The fields are:
*
* * flags - Combination of GIT_REPOSITORY_INIT flags above.
* * mode - Set to one of the standard GIT_REPOSITORY_INIT_SHARED_...
* constants above, or to a custom value that you would like.
* * workdir_path - The path to the working dir or NULL for default (i.e.
* repo_path parent on non-bare repos). IF THIS IS RELATIVE PATH,
* IT WILL BE EVALUATED RELATIVE TO THE REPO_PATH. If this is not
* the "natural" working directory, a .git gitlink file will be
* created here linking to the repo_path.
* * description - If set, this will be used to initialize the "description"
* file in the repository, instead of using the template content.
* * template_path - When GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE is set,
* this contains the path to use for the template directory. If
* this is NULL, the config or default directory options will be
* used instead.
* * initial_head - The name of the head to point HEAD at. If NULL, then
* this will be treated as "master" and the HEAD ref will be set
* to "refs/heads/master". If this begins with "refs/" it will be
* used verbatim; otherwise "refs/heads/" will be prefixed.
* * origin_url - If this is non-NULL, then after the rest of the
* repository initialization is completed, an "origin" remote
* will be added pointing to this URL.
*/
typedef struct {
uint32_t flags;
uint32_t mode;
const char *workdir_path;
const char *description;
const char *template_path;
const char *initial_head;
const char *origin_url;
} git_repository_init_options;

/**
* Create a new Git repository in the given folder with extended controls.
*
* This will initialize a new git repository (creating the repo_path
* if requested by flags) and working directory as needed. It will
* auto-detect the case sensitivity of the file system and if the
* file system supports file mode bits correctly.
*
* @param repo_out Pointer to the repo which will be created or reinitialized.
* @param repo_path The path to the repository.
* @param opts Pointer to git_repository_init_options struct.
* @return 0 or an error code on failure.
*/
GIT_EXTERN(int) git_repository_init_ext(
git_repository **repo_out,
const char *repo_path,
git_repository_init_options *opts);

/**
* Retrieve and resolve the reference pointed at by HEAD.
Expand Down Expand Up @@ -326,6 +466,11 @@ GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index
*
* Use this function to get the contents of this file. Don't forget to
* remove the file after you create the commit.
*
* @param buffer Buffer to write data into or NULL to just read required size
* @param len Length of buffer in bytes
* @param repo Repository to read prepared message from
* @return Bytes written to buffer, GIT_ENOTFOUND if no message, or -1 on error
*/
GIT_EXTERN(int) git_repository_message(char *buffer, size_t len, git_repository *repo);

Expand Down
15 changes: 6 additions & 9 deletions src/attr_file.c
Expand Up @@ -250,18 +250,15 @@ git_attr_assignment *git_attr_rule__lookup_assignment(
int git_attr_path__init(
git_attr_path *info, const char *path, const char *base)
{
ssize_t root;

/* build full path as best we can */
git_buf_init(&info->full, 0);

if (base != NULL && git_path_root(path) < 0) {
if (git_buf_joinpath(&info->full, base, path) < 0)
return -1;
info->path = info->full.ptr + strlen(base);
} else {
if (git_buf_sets(&info->full, path) < 0)
return -1;
info->path = info->full.ptr;
}
if (git_path_join_unrooted(&info->full, path, base, &root) < 0)
return -1;

info->path = info->full.ptr + root;

/* remove trailing slashes */
while (info->full.size > 0) {
Expand Down
25 changes: 18 additions & 7 deletions src/config.c
Expand Up @@ -501,17 +501,28 @@ int git_config_find_system(char *system_config_path, size_t length)
return 0;
}

int git_config_open_global(git_config **out)
int git_config_open_default(git_config **out)
{
int error;
git_buf path = GIT_BUF_INIT;
git_config *cfg = NULL;
git_buf buf = GIT_BUF_INIT;

if ((error = git_config_find_global_r(&path)) < 0)
return error;
error = git_config_new(&cfg);

error = git_config_open_ondisk(out, git_buf_cstr(&path));
git_buf_free(&path);
if (!error && !git_config_find_global_r(&buf))
error = git_config_add_file_ondisk(cfg, buf.ptr, 2);

if (!error && !git_config_find_system_r(&buf))
error = git_config_add_file_ondisk(cfg, buf.ptr, 1);

git_buf_free(&buf);

if (error && cfg) {
git_config_free(cfg);
cfg = NULL;
}

*out = cfg;

return error;
}

0 comments on commit c920e16

Please sign in to comment.