From 801b1a160558ed8b862e683c7aaf5092b0c1adb2 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 28 Jul 2019 13:21:33 +0100 Subject: Support working tree based on a commit, tag or branch --- src/git.cpp | 10 ++++++++++ src/git.h | 7 ++++++- src/repo.cpp | 16 ++++++++++++++-- src/repo.h | 4 +++- unittests/config.cpp | 37 +++++++++++++++++++++++++++++++++---- unittests/mockDefs.cpp | 2 +- unittests/service.cpp | 4 ++-- 7 files changed, 69 insertions(+), 11 deletions(-) diff --git a/src/git.cpp b/src/git.cpp index 045d146..b169fa2 100644 --- a/src/git.cpp +++ b/src/git.cpp @@ -63,6 +63,16 @@ namespace GitFS { return gitSafeGet( git_tree_entry_bypath, git_tree_entry_free, tree.get(), path.c_str() + 1); } + RefPtr Commitish(const RepositoryPtr & repo, const std::string & name) + { + return gitSafeGet( + git_reference_dwim, git_reference_free, repo.get(), name.c_str()); + } + RefPtr Resolve(const RefPtr & ref) + { + return gitSafeGet( + git_reference_resolve, git_reference_free, ref.get()); + } } } diff --git a/src/git.h b/src/git.h index 56a7cf6..068e8cf 100644 --- a/src/git.h +++ b/src/git.h @@ -14,7 +14,7 @@ namespace GitFS { void gitSafe(int (*func)(P...), A ... p) { - if (int _giterror = func(p...); _giterror != 0) { + if (int _giterror = func(p...)) { throwError(_giterror); } } @@ -61,6 +61,11 @@ namespace GitFS { using TreeEntryPtr = decltype(gitSafeGet( git_tree_entry_bypath, git_tree_entry_free, nullptr, nullptr)); TreeEntryPtr TreeEntryByPath(const TreePtr & tree, const std::string & path); + + using RefPtr = decltype(gitSafeGet( + git_reference_dwim, git_reference_free, nullptr, nullptr)); + RefPtr Commitish(const RepositoryPtr & repo, const std::string & name); + RefPtr Resolve(const RefPtr &); } } diff --git a/src/repo.cpp b/src/repo.cpp index 4059897..0da7e4a 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -11,11 +11,23 @@ std::string operator/(const std::string & a, const std::string & b) GitFS::Repo::Repo(const PropertyReader & properties) : repo(Git::RepositoryOpenBare(properties("gitdir"))), - commit(Git::CommitLookup(repo, Git::OidParse(properties("commit")))), - tree(Git::TreeLookup(repo, *git_commit_tree_id(commit.get()))), + commitish(properties("commitish") / "master"), gid(properties("gid") / "root"), uid(properties("uid") / "root") { + git_oid commitId; + if (commitish.length() == GIT_OID_HEXSZ) { + commitId = Git::OidParse(commitish); + } + else { + auto ref = Git::Commitish(repo, commitish); + isBranch = git_reference_is_branch(ref.get()); + ref = Git::Resolve(ref); + commitId = *git_reference_target(ref.get()); + } + + commit = Git::CommitLookup(repo, commitId); + tree = Git::TreeLookup(repo, *git_commit_tree_id(commit.get())); } void diff --git a/src/repo.h b/src/repo.h index 18b1057..adeac94 100644 --- a/src/repo.h +++ b/src/repo.h @@ -35,7 +35,9 @@ namespace GitFS { private: friend class Directory; friend class Blob; - Git::RepositoryPtr repo; + const Git::RepositoryPtr repo; + const std::string commitish; + bool isBranch; Git::CommitPtr commit; Git::TreePtr tree; const std::string gid, uid; diff --git a/unittests/config.cpp b/unittests/config.cpp index 0cfc22c..460a35f 100644 --- a/unittests/config.cpp +++ b/unittests/config.cpp @@ -16,10 +16,10 @@ class IdsIce : public IceTray::DryIce { public: IdsIce(const char * uid, const char * gid) : IceTray::DryIce({ "--GitFS.testrepo.gitdir=%?"_fmt(rootDir.string()), - "--GitFS.testrepo.authkey=%?"_fmt("testauth"), - "--GitFS.testrepo.gid=%?"_fmt(gid), - "--GitFS.testrepo.uid=%?"_fmt(uid), - "--GitFS.testrepo.commit=7a0ccb40084c3ab31d9856e7f689c0514c28c930", + "--GitFS.testrepo.authkey=%?"_fmt("testauth"), + "--GitFS.testrepo.gid=%?"_fmt(gid), + "--GitFS.testrepo.uid=%?"_fmt(uid), + "--GitFS.testrepo.commitish=7a0ccb40084c3ab31d9856e7f689c0514c28c930", }) {} }; @@ -30,6 +30,13 @@ const auto DIRS = btdata::make({ "/", "/src", "/unittests/fixtures" }); const auto FILES = btdata::make({ "/Jamroot.jam", "/src/repo.cpp", "/unittests/fixtures/executable" }); const auto LINKS = btdata::make({ "/unittests/fixtures/symlink" }); +const auto COMMITISHS = btdata::make({ + "", + "master", + "origin/master", + "testcommit", + "7a0ccb40084c3ab31d9856e7f689c0514c28c930" +}); BOOST_DATA_TEST_CASE(uid_gid_override_getattr, USERS * GROUPS * (DIRS + FILES + LINKS), @@ -78,4 +85,26 @@ BOOST_DATA_TEST_CASE(uid_gid_override_list, dir->close(); } +BOOST_DATA_TEST_CASE(commitishs, COMMITISHS * (FILES + DIRS), commitish, path) +{ + IceTray::DryIce di({ + "--GitFS.testrepo.gitdir=%?"_fmt(rootDir.string()), + "--GitFS.testrepo.authkey=%?"_fmt("testauth"), + "--GitFS.testrepo.commitish=%?"_fmt(commitish), + }); + VolumeClient c; + BOOST_CHECK_NO_THROW(c.v->ice_ping()); + BOOST_CHECK_NO_THROW(c.v->getattr(c.env, path)); +} + +BOOST_DATA_TEST_CASE(bad_commitishs, FILES, commitish) // File paths aren't commitishs +{ + IceTray::DryIce di({ + "--GitFS.testrepo.gitdir=%?"_fmt(rootDir.string()), + "--GitFS.testrepo.authkey=%?"_fmt("testauth"), + "--GitFS.testrepo.commitish=%?"_fmt(commitish), + }); + Client c; + BOOST_CHECK_THROW(c.s->connect("testrepo", "testauth"), NetFS::ConfigError); +} diff --git a/unittests/mockDefs.cpp b/unittests/mockDefs.cpp index dff4cbc..1ecf11c 100644 --- a/unittests/mockDefs.cpp +++ b/unittests/mockDefs.cpp @@ -9,7 +9,7 @@ GitFS::Test::Service::Service() : IceTray::DryIce({ "--GitFS.testrepo.gitdir=%?"_fmt(rootDir.string()), "--GitFS.testrepo.authkey=testauth", - "--GitFS.testrepo.commit=7a0ccb40084c3ab31d9856e7f689c0514c28c930", + "--GitFS.testrepo.commitish=7a0ccb40084c3ab31d9856e7f689c0514c28c930", }) { } diff --git a/unittests/service.cpp b/unittests/service.cpp index aaa9d85..207aa15 100644 --- a/unittests/service.cpp +++ b/unittests/service.cpp @@ -31,7 +31,7 @@ BOOST_DATA_TEST_CASE(badauth, IceTray::DryIce s({ "--GitFS.testrepo.gitdir=%?"_fmt(rootDir.string()), "--GitFS.testrepo.authkey=testauth", - "--GitFS.testrepo.commit=7a0ccb40084c3ab31d9856e7f689c0514c28c930", + "--GitFS.testrepo.commitish=7a0ccb40084c3ab31d9856e7f689c0514c28c930", }); Client c; BOOST_CHECK_NO_THROW(c.s->ice_ping()); @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(missing_repo) "--GitFS.missing.gitdir=/not/here", "--GitFS.missing.commit=7a0ccb40084c3ab31d9856e7f689c0514c28c930", "--GitFS.testrepo.gitdir=%?"_fmt(rootDir.string()), - "--GitFS.testrepo.commit=7a0ccb40084c3ab31d9856e7f689c0514c28c931", + "--GitFS.testrepo.commitish=7a0ccb40084c3ab31d9856e7f689c0514c28c931", }); Client c; BOOST_CHECK_NO_THROW(c.s->ice_ping()); -- cgit v1.2.3