On Thu, 2016-02-18 at 15:50 +0700, Duy Nguyen wrote: [snip] Thanks; applied the above > This permission makes me wonder if we need adjust_shared_perm() here > and some other places. So just add this after every mkdir? if (shared_repository) adjust_shared_perm(db_path); > > + if (ret) > > + die("BUG: mdb_env_open (%s) failed: %s", path, > > + mdb_strerror(ret)); > > +} > > + > > +static int lmdb_init_db(int shared, struct strbuf *err) > > +{ > > + /* > > + * To create a db, all we need to do is make a directory > > for > > + * it to live in; lmdb will do the rest. > > + */ > > + > > + if (!db_path) > > + db_path = > > xstrdup(real_path(git_path("refs.lmdb"))); > > + > > + if (mkdir(db_path, 0775) && errno != EEXIST) { > > + strbuf_addf(err, "%s", strerror(errno)); > > maybe strbuf_addstr, unless want to add something more, "mkdir > failed"? added more > > +static int read_per_worktree_ref(const char *submodule, const char > > *refname, > > + struct MDB_val *val, int > > *needs_free) > > From what I read, I suspect these _per_worktree functions will be > identical for the next backend. Should we just hand over the job for > files backend? For all entry points that may deal with per-worktree > refs, e.g. lmdb_resolve_ref_unsafe, can we check ref_type() first > thing, if it's per-worktree we call > refs_be_files.resolve_ref_unsafe() > instead? It could even be done at frontend level, > e.g. refs.c:resolve_ref_unsafe(). > > Though I may be talking rubbish here because I don't know how whether > it has anything to do with transactions. The reason I did it this way is that some ref chains cross backend boundaries (e.g. HEAD -> refs/heads/master). But if we have other backends later, we could generalize. > > +{ > > + struct strbuf sb = STRBUF_INIT; > > + struct strbuf path = STRBUF_INIT; > > + struct stat st; > > + int ret = -1; > > + > > + submodule_path(&path, submodule, refname); > > + > > +#ifndef NO_SYMLINK_HEAD > > It started with the compiler warns about unused "st" when this macro > is defined. Which makes me wonder, should we do something like this > to > make sure this code compiles unconditionally? > > +#ifndef NO_SYMLINK_HEAD > + int no_symlink_head = 0; > +#else > + int no_symlink_head = 1; > +#endif > ... > + if (!no_symlink_head) { > ... OK. > > +int lmdb_transaction_begin_flags(struct strbuf *err, unsigned int > > flags) > > static? yep > > +static const char *parse_ref_data(struct lmdb_transaction > > *transaction, > > + const char *refname, const char > > *ref_data, > > + unsigned char *sha1, int > > resolve_flags, > > + int *flags, int bad_name) > > +{ >[snip] > This code looks a lot like near the end of resolve_ref_1(). Maybe we > could share the code in refs/backend-common.c or something and call > here instead? When I wrote this, I couldn't find a straightforward way to factor out the commonalities, but I'll try again now that I understand the refs code better. > > +static int show_one_reflog_ent(struct strbuf *sb, > > each_reflog_ent_fn fn, void *cb_data) > > +{ > > + unsigned char osha1[20], nsha1[20]; > > + char *email_end, *message; > > + unsigned long timestamp; > > + int tz; > > + > > + /* old (raw sha) new (raw sha) name <email> SP time TAB > > msg LF */ > > Hmm.. since you're going with raw sha-1, this is clearly not a text > string anymore, any reason to still keep LF at the end? IIRC, some of the common funcs depend on this. > > +static int lmdb_delete_reflog(const char *refname) > > +{ > > + MDB_val key, val; > > + char *log_path; > > + int len; > > + MDB_cursor *cursor; > > + int ret = 0; > > + int mdb_ret; > > + struct strbuf err = STRBUF_INIT; > > + int in_transaction; > > + > > + if (ref_type(refname) != REF_TYPE_NORMAL) > > + return refs_be_files.delete_reflog(refname); > > Yay.. delegating work to files backend. I still think doing this in > refs.c:delete_reflog() may be a good idea. Yes, I agree. > > +int lmdb_reflog_expire(const char *refname, const unsigned char > > *sha1, > > static? Yep. > > +static int lmdb_create_symref(const char *ref_target, > > + const char *refs_heads_master, > > + const char *logmsg) > > +{ > > + > ... > > + mdb_put_or_die(&transaction, &key, &val, 0); > > + > > + /* TODO: Don't create ref d/f conflicts */ > > I'm not sure I get this comment. D/F conflicts are no longer a thing > for lmdb backend, right? I'm trying to avoid the lmdb backend creating a set of refs that the files backend can't handle. This would make collaboration with other versions of git more difficult. > > +MDB_env *submodule_txn_begin(struct lmdb_transaction *transaction) > > static? Yes. > > +{ > > + int ret; > > + MDB_env *submodule_env = NULL; > > + struct strbuf path = STRBUF_INIT; > > + > > + strbuf_git_path_submodule(&path, transaction->submodule, > > "refs.lmdb"); > > + > > + if (!is_directory(path.buf)) > > + goto done; > > + > > + mkdir(path.buf, 0775); > > A few other places where mkdir() is called, we may need to > adjust_shared_perm(). OK. > > diff --git a/setup.c b/setup.c > > index 1a62277..00625ab 100644 > > --- a/setup.c > > +++ b/setup.c > > @@ -279,7 +279,7 @@ int ref_storage_backend_config(const char *var, > > const char *value, void *ptr) > > * > > * - either an objects/ directory _or_ the proper > > * GIT_OBJECT_DIRECTORY environment variable > > - * - a refs/ directory > > + * - a refs.lmdb/ directory or a refs/ directory > > * - either a HEAD symlink or a HEAD file that is formatted as > > * a proper "ref:", or a regular file HEAD that has a properly > > * formatted sha1 object name. > > @@ -313,8 +313,13 @@ int is_git_directory(const char *suspect) > > > > strbuf_setlen(&path, len); > > strbuf_addstr(&path, "/refs"); > > - if (access(path.buf, X_OK)) > > - goto done; > > + > > + if (access(path.buf, X_OK)) { > > + strbuf_setlen(&path, len); > > + strbuf_addstr(&path, "/refs.lmdb"); > > + if (access(path.buf, X_OK)) > > + goto done; > > + } > > > > I think it's ok leaving this function unmodified, which means "refs" > directory will always be there and "refs.lmdb" does not matter. If > somehow "refs" is deleted, old binaries get confused anyway so we > can't delete it. OK. > > @@ -1089,8 +1089,11 @@ static int refs_from_alternate_cb(struct > > alternate_object_database *e, > > goto out; > > /* Is this a git repository with refs? */ > > memcpy(other + len - 8, "/refs", 6); > > - if (!is_directory(other)) > > - goto out; > > + if (!is_directory(other)) { > > + memcpy(other + len - 8, "/refs.lmdb", 11); > > + if (!is_directory(other)) > > + goto out; > > + } > > and probably the same here. I have no idea what this code does > though, > but if it's about detecting git directory, it should call > is_git_directory() instead. I'll back out my change, but not do the the is_git_directory thing since I don't have a strong sense of why this code is the way it is. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html