Created
September 29, 2016 08:35
-
-
Save oconnore/7ddc34aaff280ae38a20e313f8270b92 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# =================================================================== | |
# Git Configuration | |
# | |
# Bundle interface: | |
# | |
# git_repo(owner, group, path, shared, remote_name, remote, force) | |
# git_umask(owner, group, path, shared) | |
# git_worktree(owner, group, path, parent, force) | |
# git_fetch(owner, group, path, remote) | |
# git_checkout(owner, group, path, remote, branch, commit) | |
# | |
# =================================================================== | |
bundle agent git_repo(owner, group, path, shared, remote_name, remote, force) { | |
# Ensure that path is a git repository with a remote named $(remote_name) matching | |
# $(remote) url. $(force) will delete existing files if $(path) contains anything | |
# other than a git repository. | |
vars: | |
"parent" string => dirname("$(path)"); | |
"reponame" string => lastnode("$(path)", "/"); | |
classes: | |
"force" expression => strcmp("$(force)", "yes"); | |
"is_git" expression => strcmp("$(gittest[is_git])", "true"); | |
"is_not_git" expression => strcmp("$(gittest[is_git])", "false"); | |
"is_remote" expression => | |
returnszero("cd $(path) 2>/dev/null && git remote | grep -q ^$(remote_name)$ 2>&1 >/dev/null", "useshell"); | |
"is_url" expression => | |
strcmp("$(remote)", execresult("cd $(path) && git remote get-url $(remote_name)", "useshell")); | |
methods: | |
"test" | |
usebundle => git_test("$(owner)", "$(path)"), | |
useresult => "gittest"; | |
files: | |
"$(path)/." | |
create => "true", | |
perms => owner("$(owner)"); | |
force.is_not_git:: | |
"$(path)/." | |
delete => file_remove_r, | |
depth_search => depth_children, | |
file_select => select_all; | |
commands: | |
is_not_git:: | |
"git init" contain => user_group_dir_command("$(owner)", "$(group)", "022", "$(path)"); | |
!is_remote:: | |
"git remote add $(remote_name) $(remote)" | |
contain => user_group_dir_command("$(owner)", "$(group)", "022", "$(path)"); | |
is_remote.!is_url:: | |
"git remote set-url $(remote_name) $(remote)" | |
contain => user_group_dir_command("$(owner)", "$(group)", "022", "$(path)"), | |
action => cached("30", "3"); | |
} | |
bundle agent git_worktree(owner, group, path, parent, force) { | |
vars: | |
"cpath" string => canonify("gwktree_$(path)"); | |
"gitcb" string => | |
execresult("cd $(parent) && git branch -lq | sed -n 's/^\* \(.*\)/\1/p'", "useshell"); | |
classes: | |
"force" expression => strcmp("$(force)", "true"); | |
"is_parent_repo" expression => strcmp("$(parent[is_git])", "true"); | |
"is_worktree" expression => strcmp("$(worktree[is_worktree])", "true"); | |
"is_not_worktree" or => { | |
strcmp("$(worktree[is_git])", "false"), | |
strcmp("$(worktree[is_worktree])", "false") | |
}; | |
methods: | |
"test_parent" | |
usebundle => git_test("$(owner)", "$(parent)"), | |
useresult => "parent"; | |
"test_self" | |
usebundle => git_test("$(owner)", "$(path)"), | |
useresult => "worktree"; | |
files: | |
is_parent_repo:: | |
"$(path)/." | |
create => "true", | |
perms => og("$(owner)", "$(group)"); | |
force.is_parent_repo.is_not_worktree:: | |
"$(path)/." | |
delete => file_remove_r, | |
depth_search => depth_children, | |
file_select => select_all, | |
handle => "del_$(cpath)"; | |
commands: | |
force.is_parent_repo.is_not_worktree:: | |
"git worktree add -f $(path) $(gitcb)" | |
contain => user_group_dir("$(owner)", "$(group)", "$(parent)"), | |
depends_on => { "del_$(cpath)" }; | |
!force.is_parent_repo.is_not_worktree:: | |
"git worktree add -f $(path) $(gitcb)" | |
contain => user_group_dir("$(owner)", "$(group)", "$(parent)"); | |
is_parent_repo:: | |
"git worktree prune -v" | |
contain => user_group_dir("$(owner)", "$(group)", "$(parent)"); | |
} | |
bundle agent git_fetch(owner, group, path, remote, branch) { | |
commands: | |
# Ensure that we have synced with the remote | |
"git fetch $(remote) refs/heads/$(branch):refs/remotes/$(remote)/$(branch)" | |
contain => user_group_dir("$(owner)", "$(group)", "$(path)"); | |
} | |
bundle agent git_checkout(owner, group, path, share, remote, branch, commit) { | |
# | |
# Ensure that $(path) contains a checkout of the remote at a certain branch | |
# | |
# If $(linked_repo) is a non-empty path, git worktree is used to link $(path) | |
# to the git checkout at $(linked-repository). Set $(force_dup) to allow multiple | |
# copies of the same branch. | |
# | |
vars: | |
"canonical_path" string => canonify("gcheckout_$(path)"); | |
classes: | |
"done" expression => "done_$(canonical_path)"; | |
methods: | |
"git_umask" | |
usebundle => git_get_umask("$(share)"), | |
useresult => "umask", | |
handle => "umask_$(canonical_path)"; | |
"checkout_helper" | |
usebundle => | |
git_checkout_helper( "$(owner)", "$(group)", "$(path)", | |
"$(remote)", "$(branch)", "$(commit)", "$(umask[git_umask])"), | |
useresult => "helper", | |
depends_on => { "umask_$(canonical_path)" }, | |
classes => when_kept("done_$(canonical_path)"); | |
reports: | |
done:: | |
"$(helper[start])" bundle_return_value_index => "start"; | |
"$(helper[final])" bundle_return_value_index => "final"; | |
"$(helper[updated])" bundle_return_value_index => "updated"; | |
} | |
bundle agent git_umask(owner, group, path, shared) { | |
methods: | |
"get" usebundle => git_get_umask("$(shared)"), | |
useresult => "umask"; | |
"apply" usebundle => | |
git_apply_umask("$(owner)", "$(group)", "$(path)", "$(shared)", "$(umask[git_share])"); | |
} | |
# =================================================================== | |
# Helper bundles | |
# =================================================================== | |
bundle agent git_get_umask(shared) { | |
vars: | |
"share[all]" string => "0644"; | |
"share[group]" string => "0640"; | |
"share[none]" string => "0600"; | |
# Compute the umask for this user based on $(shared) | |
"umask" string => ifelse("share_all", "022", ifelse("share_group", "027", "077")); | |
"git_share" string => "$(share[$(shared)])"; | |
classes: | |
# Determine the sort of sharing we're doing based on the $(shared) variable | |
"share_all" expression => strcmp("$(shared)", "all"); | |
"share_group" or => { "share_all", strcmp("$(shared)", "group") }; | |
reports: | |
"$(umask)" bundle_return_value_index => "git_umask"; | |
"$(share[$(shared)])" bundle_return_value_index => "git_share"; | |
} | |
bundle agent git_apply_umask(owner, group, path, shared, git_config) { | |
vars: | |
# Detect if the repository is shared | |
"current_share" string => execresult( | |
"cd $(path) 2>/dev/null && git config --local --get core.sharedRepository 2>&1", "useshell"); | |
"workdirs" slist => | |
string_split( | |
execresult("cd $(path) && git worktree list --porcelain | awk '/^worktree/{print $2}'", | |
"useshell"), | |
"\n", 1000); | |
classes: | |
# Determine the sort of sharing we're doing based on the $(shared) variable | |
"share_all" expression => strcmp("$(shared)", "all"); | |
"share_group" or => { "share_all", strcmp("$(shared)", "group") }; | |
"share_changed" not => strcmp("$(current_share)", "$(git_config)"); | |
commands: | |
# Update the git umask when changed | |
share_changed:: | |
"git config --local core.sharedRepository $(git_config)" | |
contain => user_group_dir_quiet("$(owner)", "$(group)", "$(path)"); | |
files: | |
# Enforce umasks for old files | |
share_all:: | |
"$(workdirs)/." | |
depth_search => depth_all, | |
file_select => select_all, | |
perms => read_all_ug("$(owner)", "$(group)"); | |
share_group.!share_all:: | |
"$(workdirs)/." | |
depth_search => depth_all, | |
file_select => select_all, | |
perms => read_group_ug("$(owner)", "$(group)"); | |
} | |
bundle agent git_test(owner, path) { | |
# | |
# Test git worktree -- returns array[found] = true/false and array[parent] = <parent dir> | |
# | |
vars: | |
"fullpath" string => execresult("cd $(path) && pwd", "useshell"); | |
"cpath" string => canonify("$(fullpath)"); | |
"context" string => "echo \"^context=gitctx\""; | |
"git_op" string => "git worktree list --porcelain"; | |
"awk_op" string => | |
"awk '/^worktree/{if($2==\"$(fullpath)\")wtree=\"yes\";else wtree=\"no\";printf(\"=worktree[%d]=%s\n+%s_$(cpath)\n\", i++, $2, wtree);}'"; | |
"git_res" | |
string => ifelse("yes_$(cpath)", "true", "false"), | |
depends_on => { "wtree_list_$(cpath)" }; | |
"found_res" string => ifelse("yes_$(cpath).not_primary", "true", "false"), | |
depends_on => { "wtree_list_$(cpath)" }; | |
classes: | |
"not_primary" not => strcmp("$(fullpath)", "$(gitctx.worktree[0])"); | |
"done" expression => "yes_$(cpath)|no_$(cpath)"; | |
commands: | |
"if git log -n1 --format=%H >/dev/null 2>&1; then echo +git; else echo -git; fi" | |
contain => user_dir("$(owner)", "$(path)"), | |
module => "true"; | |
"$(context); $(git_op) | $(awk_op)" | |
contain => user_dir("$(owner)", "$(path)"), | |
handle => "wtree_list_$(cpath)", | |
module => "true"; | |
reports: | |
!done:: | |
"false" bundle_return_value_index => "is_git"; | |
"false" bundle_return_value_index => "is_worktree"; | |
done:: | |
"$(git_res)" bundle_return_value_index => "is_git"; | |
"$(found_res)" bundle_return_value_index => "is_worktree"; | |
"$(gitctx.worktree[0])" bundle_return_value_index => "parent"; | |
} | |
bundle agent git_checkout_helper(owner, group, path, remote, branch, commit, umask) { | |
vars: | |
"cpath" string => canonify("gchelper_$(path)"); | |
"checkout" string => "git checkout --ignore-other-worktrees -fB auto/$(branch)"; | |
"module_cmd" string => | |
"git log -n1 --format=%H | awk '{printf(\"^context=git\n=commitid=%s\n\", $1)}'"; | |
# The commit id before this bundle is enforced | |
"start_commit" string => execresult("cd $(path); git log -n1 --format=%H", "useshell"); | |
"updated" | |
string => ifelse(strcmp("$(git.commitid)", "$(start_commit)"), "false", "true"), | |
depends_on => { "checkout_$(cpath)" }; | |
classes: | |
"specified_commit" not => strcmp("$(commit)", ""); | |
"done" expression => "done_$(cpath)"; | |
commands: | |
any:: | |
"git clean -xfd" | |
contain => user_group_dir_command_noout("$(owner)", "$(group)", "$(umask)", "$(path)"); | |
!specified_commit:: | |
# Clean and sync the working directory | |
"$(checkout) $(remote)/$(branch)" | |
contain => user_group_dir_command_noout("$(owner)", "$(group)", "$(umask)", "$(path)"); | |
specified_commit:: | |
# Clean and sync the working directory | |
"$(checkout) $(commit)" | |
contain => user_group_dir_command_noout("$(owner)", "$(group)", "$(umask)", "$(path)"); | |
any:: | |
"$(module_cmd)" | |
contain => user_group_dir_command("$(owner)", "$(group)", "$(umask)", "$(path)"), | |
handle => "checkout_$(cpath)", | |
module => "true", | |
classes => when_kept("done_$(cpath)"); | |
reports: | |
done:: | |
"$(start_commit)" bundle_return_value_index => "start"; | |
"$(git.commitid)" bundle_return_value_index => "final"; | |
"$(updated)" bundle_return_value_index => "updated"; | |
} | |
# EOF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment