githelper.git / githelper.pike

version» Context lines:

githelper.git/githelper.pike:56:      string get_staged_file(string filename)   {    string sha;    if (2 != sscanf(run_git("ls-files", "--stage", "--", filename),    "%*o %s ", sha))    fail("Unable to parse output from git ls-files...\n");    return run_git("cat-file", "blob", sha);   }    - string get_committed_file(string sha, string filename) + 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)) +  return "";    if (2 != sscanf(attrentry, "%*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,
githelper.git/githelper.pike:191:    fill_one(attrs[i], attrs, all_attr);    }       mapping(string:string|int) checkattr(string path)    {    mapping(string:string|int) all_attr = ([]);    fill(path, attrs, all_attr);    return all_attr;    }    +  array(string) findattr(string attrname) +  { +  array(string) r = ({}); +  foreach(attrs, MatchAttr attr) { +  int z=0; +  foreach(attr->states, AttrState state) +  if(state->attr == attrname && state->setto == ATTR_TRUE) { +  z = 1; +  break; +  } +  if (z) +  r += ({ attr->name }); +  } +  return r; +  } +     static string _sprintf(int type) {    return type=='O' && sprintf("GitAttributes(%O)\n", attrs);    }   }            /* Hooks */      class CommitHookUtils
githelper.git/githelper.pike:353:    return 1;    }    return 0;    }       int check_blocker_attributes(string sha, GitAttributes attrs, array(string) files_to_commit)    {    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;    } -  +  }    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(sha, filename))    return 1;    }    }    return 0;    }    -  int check_gitattributes_files(string sha, array(string) files_to_commit) +  int check_gitattributes_files(string sha, array(string) files_to_commit, +  GitAttributes attrs)    {    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", sha+"^", sha, -  "--", ".gitattributes"); -  if (sizeof(diff)) { -  int pos = search(diff, "\n@@"); -  if (pos >= 0) -  diff = diff[pos+1..]; -  foreach(diff/"\n", string line) -  if(sizeof(line) && search(line, "foreign_ident")>=0 && -  search(line, "[attr]") != 1 && -  (line[0]=='+' || line[0]=='-')) { -  int code, len; -  string fn; -  if(sscanf(line, "%c/%s foreign_ident%n", code, fn, len) != 3 || -  len != sizeof(line)) { -  write("Unsupported change of foreign_ident in .gitattributes\n"); +  GitAttributes old_attrs = +  GitAttributes(get_committed_file(sha+"^", ".gitattributes", 1)); +  +  array(string) new_f_e = sort(attrs->findattr("foreign_ident")); +  array(string) old_f_e = sort(old_attrs->findattr("foreign_ident")); +  array(string) added_fe = new_f_e - old_f_e; +  array(string) removed_fe = old_f_e - new_f_e; +  +  foreach(added_fe, string path) { +  if(!has_prefix(path, "/") || search(path, "*")>=0) { +  write("Added unsupported foreign_ident: %s\n", path);    return 1;    } -  if (code=='-' && search(files_to_commit, fn)<0) { -  write("Removed foreign_ident from unstaged file %s\n", fn); +  path = path[1..]; +  if (sizeof(run_git("ls-tree", sha+"^", "--", path)) || +  !sizeof(run_git("ls-tree", sha, "--", path))) { +  write("Added foreign_ident to unadded file %s\n", path);    return 1;    }    } -  +  +  foreach(removed_fe, string path) { +  if(has_prefix(path, "/")) +  path = path[1..]; +  if (search(files_to_commit, path)<0) { +  write("Removed foreign_ident from unchanged file %s\n", path); +  return 1;    }    } -  +  }    return 0;    }       int check_commit(string sha)    {    write("Checking commit %s\n", sha);    array(string) committed_files =    split_z(run_git("diff", "--name-only", "-z", sha, sha+"^")); -  string attrentry = run_git("ls-tree", sha, "--", ".gitattributes"); -  string attrtext = ""; -  if (sizeof(attrentry)) { -  string blob; -  if (2 != sscanf(attrentry, "%*o blob %s\t", blob)) -  fail("Unexpected output from git ls-tree\n"); -  attrtext = run_git("cat-file", "blob", blob); -  } +  string attrtext = get_committed_file(sha, ".gitattributes", 1);    GitAttributes attrs = GitAttributes(attrtext);    return check_blocker_attributes(sha, attrs, committed_files) || -  check_gitattributes_files(sha, committed_files); +  check_gitattributes_files(sha, committed_files, attrs);    }       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))