Branch: Tag:

2010-09-25

2010-09-25 20:39:18 by Marcus Comstedt <marcus@mc.pp.se>

Improved attribute checking in server hook.

63:    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);
198:    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);    }
360:    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))
378:    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")) {
387:    }       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;    }   
419:    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)