diff --git a/src/tl/tl/tlGit.cc b/src/tl/tl/tlGit.cc index 9479ba5a80..13d71d123d 100644 --- a/src/tl/tl/tlGit.cc +++ b/src/tl/tl/tlGit.cc @@ -153,72 +153,93 @@ ref_matches (const char *name, const std::string &ref) } } -static void -checkout_branch (git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch) +namespace { - git_buf remote_branch = GIT_BUF_INIT_CONST (NULL, 0); - try { +class GitBuffer +{ +public: + GitBuffer () + { + m_buf = GIT_BUF_INIT_CONST (NULL, 0); + } - git_oid oid; + ~GitBuffer () + { +#if LIBGIT2_VER_MAJOR > 0 || (LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR >= 28) + git_buf_dispose (&m_buf); +#else + git_buf_free (&m_buf); +#endif + } - // if no branch is given, use the default branch - if (! branch) { - check (git_remote_default_branch (&remote_branch, remote)); - branch = remote_branch.ptr; - if (tl::verbosity () >= 10) { - tl::info << tr ("Git checkout: Using default branch for repository ") << git_remote_url (remote) << ": " << branch; - } - } else { - if (tl::verbosity () >= 10) { - tl::info << tr ("Git checkout: Checking out branch for repository ") << git_remote_url (remote) << ": " << branch; - } - } + const char *c_str () const { return m_buf.ptr; } - // resolve the branch by using ls-remote: + git_buf *get () { return &m_buf; } + const git_buf *get () const { return &m_buf; } - size_t n = 0; - const git_remote_head **ls = NULL; - check (git_remote_ls (&ls, &n, remote)); +private: + git_buf m_buf; +}; - if (tl::verbosity () >= 20) { - tl::info << "Git checkout: ls-remote on " << git_remote_url (remote) << ":"; - } +} - bool found = false; +static void +checkout_branch (git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch) +{ + GitBuffer remote_branch; + git_oid oid; - for (size_t i = 0; i < n; ++i) { - const git_remote_head *rh = ls[i]; - if (tl::verbosity () >= 20) { - char oid_fmt [80]; - git_oid_tostr (oid_fmt, sizeof (oid_fmt), &rh->oid); - tl::info << " " << rh->name << ": " << (const char *) oid_fmt; - } - if (ref_matches (rh->name, branch)) { - oid = rh->oid; - found = true; - } + // if no branch is given, use the default branch + if (! branch) { + check (git_remote_default_branch (remote_branch.get (), remote)); + branch = remote_branch.c_str (); + if (tl::verbosity () >= 10) { + tl::info << tr ("Git checkout: Using default branch for repository ") << git_remote_url (remote) << ": " << branch; } - - if (! found) { - throw tl::Exception (tl::to_string (tr ("Git checkout - Unable to resolve reference name: ")) + branch); + } else { + if (tl::verbosity () >= 10) { + tl::info << tr ("Git checkout: Checking out branch for repository ") << git_remote_url (remote) << ": " << branch; } + } - if (tl::verbosity () >= 10) { + // resolve the branch by using ls-remote: + + size_t n = 0; + const git_remote_head **ls = NULL; + check (git_remote_ls (&ls, &n, remote)); + + if (tl::verbosity () >= 20) { + tl::info << "Git checkout: ls-remote on " << git_remote_url (remote) << ":"; + } + + bool found = false; + + for (size_t i = 0; i < n; ++i) { + const git_remote_head *rh = ls[i]; + if (tl::verbosity () >= 20) { char oid_fmt [80]; - git_oid_tostr (oid_fmt, sizeof (oid_fmt), &oid); - tl::info << tr ("Git checkout: resolving ") << branch << tr (" to ") << (const char *) oid_fmt; + git_oid_tostr (oid_fmt, sizeof (oid_fmt), &rh->oid); + tl::info << " " << rh->name << ": " << (const char *) oid_fmt; } + if (ref_matches (rh->name, branch)) { + oid = rh->oid; + found = true; + } + } - check (git_repository_set_head_detached (repo, &oid)); - check (git_checkout_head (repo, co_opts)); + if (! found) { + throw tl::Exception (tl::to_string (tr ("Git checkout - Unable to resolve reference name: ")) + branch); + } - } catch (...) { - git_buf_dispose (&remote_branch); - throw; + if (tl::verbosity () >= 10) { + char oid_fmt [80]; + git_oid_tostr (oid_fmt, sizeof (oid_fmt), &oid); + tl::info << tr ("Git checkout: resolving ") << branch << tr (" to ") << (const char *) oid_fmt; } - git_buf_dispose (&remote_branch); + check (git_repository_set_head_detached (repo, &oid)); + check (git_checkout_head (repo, co_opts)); } void diff --git a/src/tl/tl/tlGit.h b/src/tl/tl/tlGit.h index cbc11bda93..68a1db83af 100644 --- a/src/tl/tl/tlGit.h +++ b/src/tl/tl/tlGit.h @@ -81,6 +81,9 @@ class TL_PUBLIC GitObject * * This method throws an exception if the directory structure could * not be obtained or downloading of one file failed. + * + * "branch" is the remote ref to use. This can be a branch name, a tag name, + * a remote ref such as "refs/heads/master" or a symbolic name such as "HEAD". */ static bool download (const std::string &url, const std::string &target, const std::string &branch, double timeout = 60.0, tl::InputHttpStreamCallback *callback = 0);