diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2017-03-04 22:37:29 +0000 | 
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2017-03-04 22:51:11 +0000 | 
| commit | 27cef443d16c6110152cfac4e667286efb83ea16 (patch) | |
| tree | 88869690300aed537ba674bcec4aaefb230f296c | |
| parent | Update GitError message writer (diff) | |
| download | gentoobrowse-api-27cef443d16c6110152cfac4e667286efb83ea16.tar.bz2 gentoobrowse-api-27cef443d16c6110152cfac4e667286efb83ea16.tar.xz gentoobrowse-api-27cef443d16c6110152cfac4e667286efb83ea16.zip | |
Create git utils
| -rw-r--r-- | gentoobrowse-api/api/impl.cpp | 4 | ||||
| -rw-r--r-- | gentoobrowse-api/api/maintenance.ice | 1 | ||||
| -rw-r--r-- | gentoobrowse-api/service/maintenanceGitOperations.cpp | 26 | ||||
| -rw-r--r-- | gentoobrowse-api/service/utils/git.cpp | 89 | ||||
| -rw-r--r-- | gentoobrowse-api/service/utils/git.h | 47 | 
5 files changed, 144 insertions, 23 deletions
| diff --git a/gentoobrowse-api/api/impl.cpp b/gentoobrowse-api/api/impl.cpp index f032c3a..9c21c98 100644 --- a/gentoobrowse-api/api/impl.cpp +++ b/gentoobrowse-api/api/impl.cpp @@ -2,10 +2,10 @@  #include <compileTimeFormatter.h>  namespace Gentoo { -	AdHocFormatter(GitErrorMessage, "Git Error: %? (code %?, class %?)"); +	AdHocFormatter(GitErrorMessage, "Git Error: %?: %? (code %?, class %?)");  	void GitError::ice_print(std::ostream & s) const  	{ -		GitErrorMessage::write(s, message, errorCode, errorClass); +		GitErrorMessage::write(s, operation, message, errorCode, errorClass);  	}  } diff --git a/gentoobrowse-api/api/maintenance.ice b/gentoobrowse-api/api/maintenance.ice index 736b913..335cd7e 100644 --- a/gentoobrowse-api/api/maintenance.ice +++ b/gentoobrowse-api/api/maintenance.ice @@ -3,6 +3,7 @@  module Gentoo {  	["cpp:ice_print"]  	exception GitError { +		string operation;  		int errorCode;  		int errorClass;  		string message; diff --git a/gentoobrowse-api/service/maintenanceGitOperations.cpp b/gentoobrowse-api/service/maintenanceGitOperations.cpp index 7c1ef81..84fe352 100644 --- a/gentoobrowse-api/service/maintenanceGitOperations.cpp +++ b/gentoobrowse-api/service/maintenanceGitOperations.cpp @@ -10,19 +10,12 @@  #include <sql/maintenance/changeLogInsert.sql.h>  #include <sql/maintenance/changeLogRepoCommits.sql.h>  #include <portage-models.h> +#include "utils/git.h"  #include "converters.h"  namespace Gentoo {  	namespace Service { -		static -		void -		gitSafe(int func) -		{ -			if (int _giterror = func < 0) { -				const git_error * e = giterr_last(); -				throw GitError(_giterror, e->klass, e->message); -			} -		} +		using namespace Utils::Git;  		static  		int @@ -42,15 +35,6 @@ namespace Gentoo {  			return 0;  		} -		template<typename R, typename ... P, typename ... A> -		std::unique_ptr<R, void(*)(R*)> -		gitSafeGet(int(*get)(R**, P...), void(*release)(R*), A ... p) -		{ -			R * r = nullptr; -			gitSafe(get(&r, p...)); -			return std::unique_ptr<R, void(*)(R*)>(r, release); -		} -  		void  		Maintenance::refreshChangeLogs(const Ice::Current & c)  		{ @@ -76,12 +60,12 @@ namespace Gentoo {  					auto startref = c.adapter->getCommunicator()->getProperties()  							->getProperty("GentooBrowseAPI.ChangeLogStart." + repoName);  					if (startref.empty()) { -						gitSafe(git_revwalk_push_head(walker.get())); +						gitSafe(git_revwalk_push_head, walker.get());  					}  					else {  						git_oid oid; -						gitSafe(git_oid_fromstr(&oid, startref.c_str())); -						gitSafe(git_revwalk_push(walker.get(), &oid)); +						gitSafe(git_oid_fromstr, &oid, startref.c_str()); +						gitSafe(git_revwalk_push, walker.get(), &oid);  					}  					git_revwalk_sorting(walker.get(), GIT_SORT_TIME); diff --git a/gentoobrowse-api/service/utils/git.cpp b/gentoobrowse-api/service/utils/git.cpp new file mode 100644 index 0000000..095c9c2 --- /dev/null +++ b/gentoobrowse-api/service/utils/git.cpp @@ -0,0 +1,89 @@ +#include "git.h" +#include <maintenance.h> +#include <execinfo.h> +#include <compileTimeFormatter.h> + +namespace Gentoo { +	namespace Utils { +		namespace Git { +			void +			throwError(void * const func, int err) +			{ +				const git_error * e = giterr_last(); +				fprintf(stderr, "func %p\n", func); +				char ** fn = backtrace_symbols(&func, 1); +				throw ::Gentoo::GitError(*fn, err, e->klass, e->message); +			} + +			int show(const git_transfer_progress * p, void *) +			{ +				fprintf(stderr, "%u / %u\n", p->total_objects, p->received_objects); +				return 0; +			} + +			AdHocFormatter(RefSpec, "refs/heads/%?:refs/remotes/%?/%?"); +			std::unique_ptr<git_annotated_commit, void (*)(git_annotated_commit*)> +			gitFetch(git_repository * repo, git_remote * remote, const char * remoteBranchName) +			{ +				git_fetch_options opts = GIT_FETCH_OPTIONS_INIT; +				opts.prune = GIT_FETCH_PRUNE; +				opts.update_fetchhead = 1; +				opts.callbacks.transfer_progress = show; +				auto localBranch = gitSafeGet(git_repository_head, git_reference_free, repo); +				auto localBranchName = gitSafeGet(git_branch_name, localBranch.get()); +				// auto remoteBranch = gitSafeGet(git_branch_upstream, git_reference_free, localBranch.get()); +				// auto remoteBranchName = gitSafeGet(git_branch_name, remoteBranch.get()); +				// auto remoteBranchName = gitSafeGet(git_remote_default_branch, remote); +				// auto remoteBranchName = "stable"; +				auto refspec = RefSpec::get(localBranchName, git_remote_name(remote), remoteBranchName); +				// fprintf(stderr, "localBranch %s\n", localBranchName); +				// fprintf(stderr, "remoteBranch %s\n", remoteBranchName.size); +				fprintf(stderr, "refspec %s\n", refspec.c_str()); +				char * s[] = { &refspec.front() }; +				git_strarray refs = { s, 1 }; +				//(void)refs; +				gitSafe(git_remote_fetch, remote, &refs, &opts, nullptr); +				return gitSafeGet(git_annotated_commit_from_revspec, git_annotated_commit_free, repo, "FETCH_HEAD"); +			} + +			git_oid +			gitFastForward(git_repository * repo, git_annotated_commit * fetch_head) +			{ +				// Test fast-forward is possible +				const git_annotated_commit * heads[] = { fetch_head }; +				git_merge_analysis_t analysis = GIT_MERGE_ANALYSIS_NONE; +				git_merge_preference_t preference = GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY; +				gitSafe(git_merge_analysis, &analysis, &preference, repo, heads, 1); + +				auto head = gitSafeGet(git_repository_head, git_reference_free, repo); +				if (analysis == GIT_MERGE_ANALYSIS_UP_TO_DATE) { +					return *git_reference_target(head.get()); +				} +				if (!(analysis & (GIT_MERGE_ANALYSIS_NORMAL | GIT_MERGE_ANALYSIS_FASTFORWARD))) { +					throw GitError("Merge analysis", 0, 0, "Could not fast-forward branch"); +				} + +				// Perform fast-forward +				auto fetch_head_id = *git_annotated_commit_id(fetch_head); +				auto fetch_head_object = gitSafeGet(git_object_lookup, git_object_free, repo, &fetch_head_id, GIT_OBJ_ANY); +				gitSafeGet(git_reference_set_target, git_reference_free, head.get(), &fetch_head_id, "fast-forward"); + +				// Checkout new head +				auto checkout_options = gitSafeGet(git_checkout_init_options, 0u + GIT_CHECKOUT_OPTIONS_VERSION); +				checkout_options.checkout_strategy = GIT_CHECKOUT_FORCE; +				gitSafe(git_checkout_head, repo, &checkout_options); +				return fetch_head_id; +			} + +			void +			updateRepository(const std::string & path, const std::string & upstream, const std::string & branch) +			{ +				auto repo = gitSafeGet(git_repository_open, git_repository_free, path.c_str()); +				auto origin = gitSafeGet(git_remote_lookup, git_remote_free, repo.get(), upstream.c_str()); +				auto fetchHead = gitFetch(repo.get(), origin.get(), branch.c_str()); +				gitFastForward(repo.get(), fetchHead.get()); +			} + +		} +	} +} diff --git a/gentoobrowse-api/service/utils/git.h b/gentoobrowse-api/service/utils/git.h new file mode 100644 index 0000000..8e70074 --- /dev/null +++ b/gentoobrowse-api/service/utils/git.h @@ -0,0 +1,47 @@ +#include <memory> +#include <git2.h> + +namespace Gentoo { +	namespace Utils { +		namespace Git { +			void throwError(void * const func, int err); + +			template<typename ... P, typename ... A> +			void +			gitSafe(int (*func)(P...), A ... p) +			{ +				if (int _giterror = func(p...) < 0) { +					throwError(&func, _giterror); +				} +			} + +			template<typename R, typename ... P, typename ... A> +			std::unique_ptr<R, void(*)(R*)> +			gitSafeGet(int(*get)(R**, P...), void(*release)(R*), A ... p) +			{ +				R * r = nullptr; +				gitSafe(get, &r, p...); +				return std::unique_ptr<R, void(*)(R*)>(r, release); +			} + +			template<typename R, typename ... P, typename ... A> +			R +			gitSafeGet(int(*get)(R*, P...), A ... p) +			{ +				R r; +				gitSafe(get, &r, p...); +				return r; +			} + +			std::unique_ptr<git_annotated_commit, void (*)(git_annotated_commit*)> +			gitFetch(git_repository * repo, git_remote * remote, const char * branch); + +			git_oid +			gitFastForward(git_repository * repo, git_annotated_commit * fetch_head); + +			void +			updateRepository(const std::string & path, const std::string & upstream, const std::string & branch); +		} +	} +} + | 
