githelper.git
/
githelper.pike
version
»
Context lines:
10
20
40
80
file
none
3
githelper.git/githelper.pike:534:
} /* Checks run before accepting a push */ class PreReceiveHook { inherit CommitHookUtilsRepo; static array(string) commits_to_check = ({});
-
int check_
tag_push
(string
old
_
sha
, string
new_sha, string ref_name
)
+
int check_
access
(string
ref
_
name
, string
user
)
{
-
+
/* Return 0 for no access, 1 for basic access, and 2 for full
+
access (including rebase/delete branch, and move/delete tag) */
+
string shortref = ref_name;
+
sscanf(shortref, "refs/%*[^/]/%s", shortref);
+
if (has_prefix(shortref, "scratch/") || has_prefix(shortref, user+"/"))
+
return 2;
+
if (search(ref_name, "/x-") >= 0) {
+
write("The ref %s can only be modified by its owner\n", ref_name);
+
return 0;
+
}
+
return 1;
+
}
+
+
int check_tag_push(string old_sha, string new_sha, string ref_name,
+
int access_level)
+
{
+
if (access_level >= 2)
+
return 0;
+
string oldtag = String.trim_all_whites(run_git_ex(1, "rev-parse", "--verify", "-q", ref_name)); if (sizeof(oldtag) && oldtag != new_sha) {
-
write("Tag %s already exists with value %s, will not
move
it\n",
-
ref_name, oldtag);
+
write("Tag %s already exists with value %s, will not
%s
it\n",
+
ref_name, oldtag
, (new_sha == "0"*40? "delete":"move"
)
)
;
return 1; }
-
+
if (!sizeof(oldtag) && search(ref_name[10..], "/") >= 0) {
+
write("Common tags are not allowed to contain /.\n");
+
return 1;
+
}
+
return 0; }
-
int check_branch_push(string old_sha, string new_sha, string ref_name)
+
int check_branch_push(string old_sha, string new_sha, string ref_name
,
+
int access_level
)
{ if (old_sha == "0"*40) {
-
// New branch,
maybe
check if the name is allowed...
+
// New branch, check if the name is allowed...
+
if (sscanf(ref_name, "refs/heads/%*[0-9.]%*c") < 2) {
+
write("Main version branches can not be created remotely.\n");
+
return 1;
+
}
+
if (access_level < 2 && search(ref_name[11..], "/")>=0) {
+
write("Common topic branch names are not allowed to contain /.\n");
+
return 1;
+
}
return 0;
-
+
} else if (new_sha == "0"*40) {
+
// Delete old branch
+
if (access_level < 2) {
+
write("You may not delete branches which do not belong to you.\n");
+
return 1;
+
}
+
return 0;
} else {
-
+
if (access_level >= 2)
+
/* Skip checks */
+
return 0;
+
string merge_base = String.trim_all_whites(run_git("merge-base", old_sha, new_sha)); if (merge_base != old_sha) { write("Push to %s is not fast-forward.\n", ref_name); return 1; } array(string) fp_path = split_lf(run_git("rev-list", "--first-parent", old_sha+"^.."+new_sha)); if (search(fp_path, old_sha)<0) { write("Commit %s does not contain %s in its first-parent ancestry.\nDid you pull with merge instead of rebase?\n", new_sha, old_sha); return 1; } commits_to_check += split_lf(run_git("rev-list", old_sha+".."+new_sha)); return 0; } } int check_push(string old_sha, string new_sha, string ref_name) {
-
+
string git_user = getenv("GIT_USER")||getenv("USER")||"nobody";
+
int access_level;
+
if(!(access_level = check_access(ref_name, git_user))) return 1;
if (has_prefix(ref_name, "refs/tags/")) {
-
return check_tag_push(old_sha, new_sha, ref_name);
+
return check_tag_push(old_sha, new_sha, ref_name
, access_level
);
} else if (has_prefix(ref_name, "refs/heads/")) {
-
return check_branch_push(old_sha, new_sha, ref_name);
+
return check_branch_push(old_sha, new_sha, ref_name
, access_level
);
} else { write("Trying to push a ref which is neither under refs/tags/ or refs/heads/...\n"); return 1; } } int hook() { foreach(split_lf(Stdio.stdin->read()), string line) { array(string) args = line / " ";