submit and author resubmits: the commit must be a hash git knows (checked in the author's workdir or the Logbook checkout) and is stored in full; HEAD, placeholders and unknown hashes are refused
This commit is contained in:
1 parent
a92efdad45
commit
eb948ddda1
3 files changed
+34
-2
No files matched your search
@@ -761,6 +761,7 @@ class Harbor(WorkMixin, ExtrasMixin, FlowMixin, LaunchMixin):
|
||||
if not reviewers:
|
||||
raise HarborError("no reviewer: name one, or set reviewers in the project file")
|
||||
canonical = parse_scope(scope)[0] if scope else None
|
||||
commit = self.resolve_commit(author, commit)
|
||||
|
||||
def do(c):
|
||||
now = self.now()
|
||||
@@ -822,6 +823,8 @@ class Harbor(WorkMixin, ExtrasMixin, FlowMixin, LaunchMixin):
|
||||
self.require_running(agent, "move review items")
|
||||
if to_state == "landed":
|
||||
self.check_landing_policy(item_id)
|
||||
if is_author and commit:
|
||||
commit = self.resolve_commit(agent, commit)
|
||||
|
||||
def do(c):
|
||||
now = self.now()
|
||||
|
||||
@@ -39,6 +39,29 @@ def _git(workdir, *args):
|
||||
|
||||
|
||||
class FlowMixin:
|
||||
def resolve_commit(self, agent, commit):
|
||||
"""The full hash of a commit an item names, checked in agent's workdir (or the Logbook's decomp checkout).
|
||||
A placeholder ('HEAD', 'PLACEHOLDER') or a hash git does not know is refused; without any git checkout to
|
||||
ask, the value is kept as given."""
|
||||
if not commit:
|
||||
return commit
|
||||
commit = str(commit).strip()
|
||||
spec = next((a for a in self.project.agents if a["name"] == agent), {})
|
||||
places = [spec.get("workdir"), (self.project.logbook or {}).get("decomp")]
|
||||
repos = [p for p in places if p and (Path(p) / ".git").exists()]
|
||||
if not repos:
|
||||
return commit
|
||||
if not re.fullmatch(r"[0-9a-fA-F]{7,40}", commit):
|
||||
raise HarborError(f"commit {commit!r} is not a hash: give the commit's hash (git rev-parse HEAD), "
|
||||
"not a branch name, HEAD or a placeholder")
|
||||
for repo in repos:
|
||||
try:
|
||||
return _git(repo, "rev-parse", "--verify", "--quiet", f"{commit}^{{commit}}").strip()
|
||||
except (RuntimeError, subprocess.TimeoutExpired):
|
||||
continue
|
||||
raise HarborError(f"commit {commit} is not in the repository: commit your work first and give the hash "
|
||||
"git rev-parse HEAD prints")
|
||||
|
||||
def worktree_change(self, agent):
|
||||
"""(mtime, path) of the most recently modified uncommitted file in agent's worktree, or None."""
|
||||
spec = next((a for a in self.project.agents if a["name"] == agent), {})
|
||||
|
||||
+8
-2
@@ -81,13 +81,19 @@ class Flow(unittest.TestCase):
|
||||
self.h.run_template("Lead", "nope")
|
||||
|
||||
def test_policies(self):
|
||||
item = self.h.submit("Ann", "x", commit="abc")
|
||||
head, older = subprocess.run(["git", "-C", str(self.dir / "wt-ann"), "rev-parse", "HEAD", "HEAD~1"],
|
||||
capture_output=True, text=True, check=True).stdout.split()
|
||||
for bad in ("HEAD", "PLACEHOLDER", "abc", "0123456789abcdef"): # not a hash, or not in git
|
||||
with self.assertRaises(HarborError):
|
||||
self.h.submit("Ann", "x", commit=bad)
|
||||
item = self.h.submit("Ann", "x", commit=head[:8])
|
||||
self.assertEqual(self.h.item(item["id"])[0]["commit_hash"], head) # stored in full
|
||||
self.h.transition("Lead", item["id"], "approved")
|
||||
with self.assertRaises(HarborError):
|
||||
self.h.transition("Lead", item["id"], "landed", commit="b4") # Rev has not approved
|
||||
self.h.transition("Rev", item["id"], "approved") if False else None
|
||||
self.h.transition("Lead", item["id"], "changes_requested")
|
||||
self.h.transition("Ann", item["id"], "submitted", commit="def")
|
||||
self.h.transition("Ann", item["id"], "submitted", commit=older)
|
||||
self.h.transition("Rev", item["id"], "approved")
|
||||
self.h.transition("Lead", item["id"], "landed", commit="b4")
|
||||
self.h.send("Ann", "All", "one")
|
||||
|
||||
Reference in new issue
Block a user