diff --git a/pygit2/__init__.py b/pygit2/__init__.py index 244fdad1e..d291dd247 100644 --- a/pygit2/__init__.py +++ b/pygit2/__init__.py @@ -37,14 +37,39 @@ from .version import __version__ -def init_repository(path, bare=False): +def init_repository(path, bare=False, **kw): """ Creates a new Git repository in the given *path*. If *bare* is True the repository will be bare, i.e. it will not have a working copy. + + Keyword options: + + **shared** allows setting the permissions on the repository. Accepted + values are 'false', 'uname', 'true', 'group', 'all', 'everybody', 'world', + or an octal string, e.g. '0660'. + + **template_dir** A directory of templates to use instead of the default. + It is not currently implemented in libgit, so this has no effect yet. + + **working_dir** The directory to use as the working tree. If this is + specified, the git repository at **path** will have its working directory + set to this value. + + **initial_head** if specified, points HEAD at this reference. If it begins + with 'refs/', the value will be used verbatim. Otherwise 'refs/heads/' will + be prefixed to the value. + + **origin_url** if specified, an 'origin' remote will be added that points + at this URL. """ - _pygit2.init_repository(path, bare) + + if 'working_dir' in kw: # Overrides the relative path behaviour in libgit + from os.path import abspath + kw['working_dir'] = str(abspath(kw['working_dir'])) + + _pygit2.init_repository(path, bare, **kw) return Repository(path) diff --git a/src/pygit2.c b/src/pygit2.c index 77535c735..dee4b84f7 100644 --- a/src/pygit2.c +++ b/src/pygit2.c @@ -85,7 +85,7 @@ extern PyTypeObject MergeResultType; PyDoc_STRVAR(init_repository__doc__, - "init_repository(path, bare)\n" + "init_repository(path, **options)\n" "\n" "Creates a new Git repository in the given path.\n" "\n" @@ -94,22 +94,104 @@ PyDoc_STRVAR(init_repository__doc__, "path\n" " Path where to create the repository.\n" "\n" + "Optional arguments:\n" + "\n" "bare\n" - " Whether the repository will be bare or not.\n"); + " Whether the repository will be bare or not.\n" + "\n" + "shared\n" + " Allows setting the permissions on the repository.\n" + "\n" + "template_dir\n" + " A directory of templates to use instead of the default.\n" + "\n" + "working_dir\n" + " The directory to use as the working tree.\n" + "\n" + "initial_head\n" + " Points HEAD at this reference.\n" + "\n" + "origin_url\n" + " An 'origin' remote will be added that points at this URL.\n"); PyObject * -init_repository(PyObject *self, PyObject *args) { +init_repository(PyObject *self, PyObject *args, PyObject *kw) { git_repository *repo; const char *path; - unsigned int bare; + unsigned int bare = 0; + const char *shared = NULL; + const char *template_dir = NULL; + const char *working_dir = NULL; + const char *initial_head = NULL; + const char *origin_url = NULL; + unsigned int shared_value = 0; int err; - if (!PyArg_ParseTuple(args, "sI", &path, &bare)) + static char * kwlist[] = { + "path", "bare", "shared", "template_dir", + "working_dir", "initial_head", "origin_url", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "s|Isssss", kwlist, + &path, &bare, &shared, &template_dir, + &working_dir, &initial_head, &origin_url)) return NULL; - err = git_repository_init(&repo, path, bare); - if (err < 0) - return Error_set_str(err, path); + if (!shared &&!template_dir && !working_dir && !initial_head && !origin_url) { + err = git_repository_init(&repo, path, bare); + if (err < 0) + return Error_set_str(err, path); + } + + else { + git_repository_init_options initopts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + initopts.flags = GIT_REPOSITORY_INIT_MKPATH; + + if (bare) + initopts.flags |= GIT_REPOSITORY_INIT_BARE; + + if (template_dir) { + initopts.flags |= GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; + initopts.template_path = template_dir; + } + + if (working_dir) + initopts.workdir_path = working_dir; + + if (initial_head) + initopts.initial_head = initial_head; + + if (origin_url) + initopts.origin_url = origin_url; + + /* Parse `shared` options: false, umask, true, group, all, world, everybody, & octal values */ + if (shared) { + if (!strcmp(shared, "false") || !strcmp(shared, "umask")) + shared_value = GIT_REPOSITORY_INIT_SHARED_UMASK; + + else if (!strcmp(shared, "true") || !strcmp(shared, "group")) + shared_value = GIT_REPOSITORY_INIT_SHARED_GROUP; + + else if (!strcmp(shared, "all") || !strcmp(shared, "world") || + !strcmp(shared, "everybody")) + shared_value = GIT_REPOSITORY_INIT_SHARED_ALL; + + else if (shared[0] == '0') { + char *end = NULL; + shared_value = (unsigned int) strtol(shared + 1, &end, 8); + if (end == shared + 1 || *end != 0) { + PyErr_SetString(PyExc_ValueError, "Invalid octal value for 'shared'."); + return NULL; + } + } + + if (shared_value) + initopts.mode = shared_value; + } + + err = git_repository_init_ext(&repo, path, &initopts); + if (err < 0) + return Error_set_str(err, path); + } git_repository_free(repo); Py_RETURN_NONE; @@ -237,7 +319,7 @@ hash(PyObject *self, PyObject *args) PyMethodDef module_methods[] = { - {"init_repository", init_repository, METH_VARARGS, init_repository__doc__}, + {"init_repository", (PyCFunction) init_repository, METH_VARARGS|METH_KEYWORDS, init_repository__doc__}, {"clone_repository", clone_repository, METH_VARARGS, clone_repository__doc__}, {"discover_repository", discover_repository, METH_VARARGS,