summaryrefslogtreecommitdiff
path: root/src/fileops.c
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2011-03-18 19:38:49 +0200
committerVicent Marti <tanoku@gmail.com>2011-03-20 21:45:11 +0200
commit72a3fe42fb7208712bbe8f0981f4c6274c05e9c3 (patch)
treeb073a1c36b3215d94b1e78a0f294d7aa30d949df /src/fileops.c
parentbb3de0c472b2d5d6b8091c190bee3db79c4b5e27 (diff)
downloadlibgit2-72a3fe42fb7208712bbe8f0981f4c6274c05e9c3.tar.gz
I broke your bindings
Hey. Apologies in advance -- I broke your bindings. This is a major commit that includes a long-overdue redesign of the whole object-database structure. This is expected to be the last major external API redesign of the library until the first non-alpha release. Please get your bindings up to date with these changes. They will be included in the next minor release. Sorry again! Major features include: - Real caching and refcounting on parsed objects - Real caching and refcounting on objects read from the ODB - Streaming writes & reads from the ODB - Single-method writes for all object types - The external API is now partially thread-safe The speed increases are significant in all aspects, specially when reading an object several times from the ODB (revwalking) and when writing big objects to the ODB. Here's a full changelog for the external API: blob.h ------ - Remove `git_blob_new` - Remove `git_blob_set_rawcontent` - Remove `git_blob_set_rawcontent_fromfile` - Rename `git_blob_writefile` -> `git_blob_create_fromfile` - Change `git_blob_create_fromfile`: The `path` argument is now relative to the repository's working dir - Add `git_blob_create_frombuffer` commit.h -------- - Remove `git_commit_new` - Remove `git_commit_add_parent` - Remove `git_commit_set_message` - Remove `git_commit_set_committer` - Remove `git_commit_set_author` - Remove `git_commit_set_tree` - Add `git_commit_create` - Add `git_commit_create_v` - Add `git_commit_create_o` - Add `git_commit_create_ov` tag.h ----- - Remove `git_tag_new` - Remove `git_tag_set_target` - Remove `git_tag_set_name` - Remove `git_tag_set_tagger` - Remove `git_tag_set_message` - Add `git_tag_create` - Add `git_tag_create_o` tree.h ------ - Change `git_tree_entry_2object`: New signature is `(git_object **object_out, git_repository *repo, git_tree_entry *entry)` - Remove `git_tree_new` - Remove `git_tree_add_entry` - Remove `git_tree_remove_entry_byindex` - Remove `git_tree_remove_entry_byname` - Remove `git_tree_clearentries` - Remove `git_tree_entry_set_id` - Remove `git_tree_entry_set_name` - Remove `git_tree_entry_set_attributes` object.h ------------ - Remove `git_object_new - Remove `git_object_write` - Change `git_object_close`: This method is now *mandatory*. Not closing an object causes a memory leak. odb.h ----- - Remove type `git_rawobj` - Remove `git_rawobj_close` - Rename `git_rawobj_hash` -> `git_odb_hash` - Change `git_odb_hash`: New signature is `(git_oid *id, const void *data, size_t len, git_otype type)` - Add type `git_odb_object` - Add `git_odb_object_close` - Change `git_odb_read`: New signature is `(git_odb_object **out, git_odb *db, const git_oid *id)` - Change `git_odb_read_header`: New signature is `(size_t *len_p, git_otype *type_p, git_odb *db, const git_oid *id)` - Remove `git_odb_write` - Add `git_odb_open_wstream` - Add `git_odb_open_rstream` odb_backend.h ------------- - Change type `git_odb_backend`: New internal signatures are as follows int (* read)(void **, size_t *, git_otype *, struct git_odb_backend *, const git_oid *) int (* read_header)(size_t *, git_otype *, struct git_odb_backend *, const git_oid *) int (* writestream)(struct git_odb_stream **, struct git_odb_backend *, size_t, git_otype) int (* readstream)( struct git_odb_stream **, struct git_odb_backend *, const git_oid *) - Add type `git_odb_stream` - Add enum `git_odb_streammode` Signed-off-by: Vicent Marti <tanoku@gmail.com>
Diffstat (limited to 'src/fileops.c')
-rw-r--r--src/fileops.c90
1 files changed, 86 insertions, 4 deletions
diff --git a/src/fileops.c b/src/fileops.c
index 76e689e8a..237a16a9f 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -2,13 +2,13 @@
#include "fileops.h"
#include <ctype.h>
-static int force_path(const char *to)
+int gitfo_mkdir_2file(const char *file_path)
{
const int mode = 0755; /* or 0777 ? */
int error = GIT_SUCCESS;
char target_folder_path[GIT_PATH_MAX];
- error = git__dirname_r(target_folder_path, sizeof(target_folder_path), to);
+ error = git__dirname_r(target_folder_path, sizeof(target_folder_path), file_path);
if (error < GIT_SUCCESS)
return error;
@@ -25,6 +25,87 @@ static int force_path(const char *to)
return GIT_SUCCESS;
}
+static int creat_tempfile(char *path_out, const char *tmp_dir, const char *filename)
+{
+ int fd;
+
+ git__joinpath(path_out, tmp_dir, filename);
+ strcat(path_out, "_git2_XXXXXX");
+
+#ifdef GIT_WIN32
+ /* FIXME: there may be race conditions when multi-threading
+ * with the library */
+ if (_mktemp_s(path_out, GIT_PATH_MAX) != 0)
+ return GIT_EOSERR;
+
+ fd = gitfo_creat(path_out, 0744);
+#else
+ fd = mkstemp(path_out);
+#endif
+
+ return fd >= 0 ? fd : GIT_EOSERR;
+}
+
+static const char *find_tmpdir(void)
+{
+ static int tmpdir_not_found = 0;
+ static char temp_dir[GIT_PATH_MAX];
+ static const char *env_vars[] = {
+ "TEMP", "TMP", "TMPDIR"
+ };
+
+ unsigned int i, j;
+ char test_file[GIT_PATH_MAX];
+
+ if (tmpdir_not_found)
+ return NULL;
+
+ if (temp_dir[0] != '\0')
+ return temp_dir;
+
+ for (i = 0; i < ARRAY_SIZE(env_vars); ++i) {
+ char *env_path;
+
+ env_path = getenv(env_vars[i]);
+ if (env_path == NULL)
+ continue;
+
+ strcpy(temp_dir, env_path);
+
+ /* Fix backslashes because Windows environment vars
+ * are probably fucked up */
+ for (j = 0; j < strlen(temp_dir); ++j)
+ if (temp_dir[j] == '\\')
+ temp_dir[j] = '/';
+
+ if (creat_tempfile(test_file, temp_dir, "writetest") >= 0) {
+ gitfo_unlink(test_file);
+ return temp_dir;
+ }
+ }
+
+ /* last resort: current folder. */
+ strcpy(temp_dir, "./");
+ if (creat_tempfile(test_file, temp_dir, "writetest") >= 0) {
+ gitfo_unlink(test_file);
+ return temp_dir;
+ }
+
+ tmpdir_not_found = 1;
+ return NULL;
+}
+
+int gitfo_creat_tmp(char *path_out, const char *filename)
+{
+ const char *tmp_dir;
+
+ tmp_dir = find_tmpdir();
+ if (tmp_dir == NULL)
+ return GIT_EOSERR;
+
+ return creat_tempfile(path_out, tmp_dir, filename);
+}
+
int gitfo_open(const char *path, int flags)
{
int fd = open(path, flags | O_BINARY);
@@ -39,7 +120,7 @@ int gitfo_creat(const char *path, int mode)
int gitfo_creat_force(const char *path, int mode)
{
- if (force_path(path) < GIT_SUCCESS)
+ if (gitfo_mkdir_2file(path) < GIT_SUCCESS)
return GIT_EOSERR;
return gitfo_creat(path, mode);
@@ -117,6 +198,7 @@ int gitfo_isdir(const char *path)
int gitfo_exists(const char *path)
{
+ assert(path);
return access(path, F_OK);
}
@@ -198,7 +280,7 @@ int gitfo_mv(const char *from, const char *to)
int gitfo_mv_force(const char *from, const char *to)
{
- if (force_path(to) < GIT_SUCCESS)
+ if (gitfo_mkdir_2file(to) < GIT_SUCCESS)
return GIT_EOSERR;
return gitfo_mv(from, to);