githelper.git
/
githelper.pike
version
»
Context lines:
10
20
40
80
file
none
3
githelper.git/githelper.pike:47:
fail("git exited with code %d\n", res->exitcode); } return res->stdout; } string run_git(string ... args) { return run_git_ex(0, @args); }
-
string get_staged_file(string filename)
+
string get_staged_file(string filename
, int|void allow_empty
)
{
-
string
sha
;
-
if
(2
!
=
sscanf(
run_git("ls-files", "--stage", "--", filename)
,
-
"%*o %s ",
sha
))
+
string
blob
;
+
string
treeentry
= run_git("ls-files", "--stage", "--", filename)
;
+
if
(allow_empty
&&
!sizeof(treeentry))
+
return
"";
+
if
(2
!=
sscanf(treeentry,
"%*o %s ",
blob
))
fail("Unable to parse output from git ls-files...\n");
-
return run_git("cat-file", "blob",
sha
);
+
return run_git("cat-file", "blob",
blob
);
} string get_committed_file(string sha, string filename, int|void allow_empty) { string blob;
-
string
attrentry
= run_git("ls-tree", sha, "--", filename);
-
if (allow_empty && !sizeof(
attrentry
))
+
string
treeentry
= run_git("ls-tree", sha, "--", filename);
+
if (allow_empty && !sizeof(
treeentry
))
return "";
-
if (2 != sscanf(
attrentry
, "%*o blob %s\t", blob))
+
if (2 != sscanf(
treeentry
, "%*o blob %s\t", blob))
fail("Unexpected output from git ls-tree\n"); return run_git("cat-file", "blob", blob); } class GitAttributes { enum { ATTR_TRUE = 1, ATTR_FALSE = 2, ATTR_UNSET = 3
githelper.git/githelper.pike:221:
} } /* Hooks */ class CommitHookUtils { static array(string) files_to_commit;
+
GitAttributes attrs;
-
string get_file(string filename);
+
string get_file(string filename
, int|void allow_empty
);
+
int entry_is_new(string filename) { return 0; }
int find_expanded_ident(string data) { int p=0; while ((p = search(data, "$Id", p))>=0) { if (data[p..p+3] != "$Id$") return 1; p += 4; } return 0;
githelper.git/githelper.pike:248:
write("File %s contains an expanded ident.\n", filename); if(this_program == PreCommitHook) { write("Try 'git reset %s; git add %s', " "or remove the ident manually.\n", @({filename})*2);; } return 1; } return 0; }
+
+
int check_blocker_attributes()
+
{
+
foreach(files_to_commit, string filename) {
+
mapping(string:string|int) a = attrs->checkattr(filename);
+
if(a->foreign_ident == GitAttributes.ATTR_TRUE) {
+
if (!entry_is_new(filename)) {
+
write("File %s has the foreign_ident attribute. Please remove it before commit.\n", filename);
+
return 1;
}
-
+
}
+
if(stringp(a->block_commit) || a->block_commit == GitAttributes.ATTR_TRUE) {
+
if (!entry_is_new(filename)) {
+
write("File %s is blocked from committing: %s\n", filename,
+
replace((stringp(a->block_commit)? a->block_commit :
+
"no explanation given"), "-", " "));
+
return 1;
+
}
+
}
+
if(a->ident && a->ident != GitAttributes.ATTR_FALSE &&
+
a->ident != GitAttributes.ATTR_UNSET) {
+
if (check_ident(filename))
+
return 1;
+
}
+
}
+
return 0;
+
}
+
}
/* Checks run before editing a commit message */ class PreCommitHook { inherit CommitHookUtils;
-
string get_file(string filename)
+
string get_file(string filename
, int|void allow_empty
)
{
-
return get_staged_file(filename);
+
return get_staged_file(filename
, allow_empty
);
} int check_attributes_staged() { // We don't allow .gitattributes to differ between wt and index, // because that could mean the committed stuff ends up with different // attributes than they have right now... if (sizeof(run_git("diff", "--name-only", ".gitattributes"))) { write("You have unstaged changes to .gitattributes.\n" "Please add or stash them before commit.\n"); return 1; } }
-
int check_blocker_attributes()
-
{
-
constant attrs_to_check = ({ "foreign_ident", "block_commit", "ident" });
-
foreach(run_git("check-attr", @attrs_to_check,
-
"--", @files_to_commit) / "\n" - ({""}),
-
string line) {
-
array(string) parts = line / ": ";
-
if (sizeof(parts) != 3)
-
fail("Unexpected output from git check-attr, please fix check_blocker_attributes()\n");
-
[string filename, string attribute, string value] = parts;
-
if (value != "unspecified") {
-
switch (attribute) {
-
case "foreign_ident":
-
write("File %s has the foreign_ident attribute. Please remove it before commit.\n", filename);
-
return 1;
-
case "block_commit":
-
write("File %s is blocked from committing: %s\n", filename,
-
replace(value, "-", " "));
-
return 1;
-
case "ident":
-
if (value == "unset")
-
break;
-
if (check_ident(filename))
-
return 1;
-
break;
-
}
-
}
-
}
-
return 0;
-
}
-
+
int check_gitattributes_files() { foreach(files_to_commit, string filename) if(has_suffix(filename, "/.gitattributes")) { write(".gitattributes are not allowed in subdirectories\n"); return 1; } if(search(files_to_commit, ".gitattributes")>=0) { string diff = run_git("diff", "-p", "--cached",
githelper.git/githelper.pike:345:
} } } return 0; } int hook() { files_to_commit = split_z(run_git("diff", "--staged", "--name-only", "-z"));
+
attrs = GitAttributes(get_file(".gitattributes", 1));
return check_attributes_staged() || check_blocker_attributes() || check_gitattributes_files(); } } /* Checks run before accepting a push */ class PreReceiveHook { inherit CommitHookUtils; static string sha;
-
string get_file(string filename)
+
string get_file(string filename
, int|void allow_empty
)
{
-
return get_committed_file(sha, filename);
+
return get_committed_file(sha, filename
, allow_empty
);
}
-
int
check
_
blocker
_
attributes
(
GitAttributes
attrs
)
+
int
entry
_
is
_
new
(
string
filename
)
{
-
foreach(files_to_commit,
string filename) {
-
mapping
(
string:string|int) a = attrs->checkattr(filename);
-
if(a->foreign_ident == GitAttributes.ATTR_TRUE) {
-
if (
sizeof(run_git("ls-tree", sha+"^", "--", filename))
||
-
!
sizeof(run_git("ls-tree", sha, "--", filename))
) {
-
write("File %s has the foreign_ident attribute. Please remove it before commit.\n", filename)
;
-
return 1;
+
return
(
!
sizeof(run_git("ls-tree", sha+"^", "--", filename))
)
&&
+
sizeof(run_git("ls-tree", sha, "--", filename));
}
-
}
-
if(stringp(a->block_commit) || a->block_commit == GitAttributes.ATTR_TRUE) {
-
if (sizeof(run_git("ls-tree", sha+"^", "--", filename)) ||
-
!sizeof(run_git("ls-tree", sha, "--", filename))) {
-
write("File %s is blocked from committing: %s\n", filename,
-
replace((stringp(a->block_commit)? a->block_commit :
-
"no explanation given"), "-", " "));
-
return 1;
-
}
-
}
-
if(a->ident && a->ident != GitAttributes.ATTR_FALSE &&
-
a->ident != GitAttributes.ATTR_UNSET) {
-
if (check_ident(filename))
-
return 1;
-
}
-
}
-
return 0;
-
}
+
-
int check_gitattributes_files(
GitAttributes attrs
)
+
int check_gitattributes_files()
{ foreach(files_to_commit, string filename) if(has_suffix(filename, "/.gitattributes")) { write(".gitattributes are not allowed in subdirectories\n"); return 1; } if(search(files_to_commit, ".gitattributes")>=0) { GitAttributes old_attrs = GitAttributes(get_committed_file(sha+"^", ".gitattributes", 1));
githelper.git/githelper.pike:442:
} return 0; } int check_commit(string sha) { write("Checking commit %s\n", sha); this_program::sha = sha; files_to_commit = split_z(run_git("diff", "--name-only", "-z", sha, sha+"^"));
-
string
attrtext
= get_
committed_
file(
sha,
".gitattributes", 1)
;
-
GitAttributes attrs = GitAttributes(attrtext
);
-
return check_blocker_attributes(
attrs
) ||
-
check_gitattributes_files(
attrs
);
+
attrs
=
GitAttributes(
get_file(".gitattributes", 1));
+
return check_blocker_attributes() ||
+
check_gitattributes_files();
} int check_push(string old_sha, string new_sha, string ref_name) { if(old_sha == "0"*40) { // New ref, maybe check if the name is allowed... return 0; } else { foreach(run_git("rev-list", old_sha+".."+new_sha)/"\n", string sha) if(sizeof(sha) && check_commit(sha))