vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Serve changes at /r/<repo>/changes
8fb7aabf534adf208cd795724b1e3d287dc62f5a · Keenan Nemetz · 3d ago · parent b492b557
Serve changes at /r/<repo>/changes The metadata tree and the interface say changes; the browser was the last place spelling the route requests. Rename every method on that subtree and the URLs the server builds: redirects, activity and search results, the number alias, code links, templates, and the CLI's page links. The old route is gone rather than aliased. Nothing has been publicly released, so there is no bookmark or client to keep working, and a redirect would leave two spellings of the same page in the code. Refs #204 (01M6S6685JFG8S64ZFF452217W).
server/integration_test.go +13−13
| @@ -1319,7 +1319,7 @@ func TestEmptyStatesPrintAWorkingCommand(t *testing.T) { | |||
| 1319 | 1319 | f.publish(f.repo) | |
| 1320 | 1320 | for _, c := range []struct{ path, want string }{ | |
| 1321 | 1321 | {"/r/" + f.repo + "/issues", "vole issue new --title"}, | |
| 1322 | {"/r/" + f.repo + "/requests", "vole change new --title"}, | ||
| 1322 | {"/r/" + f.repo + "/changes", "vole change new --title"}, | ||
| 1323 | 1323 | } { | |
| 1324 | 1324 | code, body := f.get(c.path) | |
| 1325 | 1325 | if code != 200 { | |
| @@ -1370,7 +1370,7 @@ func TestRequestPageSaysWhenItWouldConflict(t *testing.T) { | |||
| 1370 | 1370 | t.Fatalf("request push: %v", err) | |
| 1371 | 1371 | } | |
| 1372 | 1372 | ||
| 1373 | code, body := f.get("/r/" + f.repo + "/requests/" + reqID) | ||
| 1373 | code, body := f.get("/r/" + f.repo + "/changes/" + reqID) | ||
| 1374 | 1374 | if code != 200 { | |
| 1375 | 1375 | t.Fatalf("request page: %d", code) | |
| 1376 | 1376 | } | |
| @@ -1393,7 +1393,7 @@ func TestRequestPageSaysWhenItWouldConflict(t *testing.T) { | |||
| 1393 | 1393 | }, "clean request"); err != nil { | |
| 1394 | 1394 | t.Fatalf("clean request push: %v", err) | |
| 1395 | 1395 | } | |
| 1396 | if _, body := f.get("/r/" + f.repo + "/requests/" + cleanID); !strings.Contains(body, "Merges into main cleanly.") { | ||
| 1396 | if _, body := f.get("/r/" + f.repo + "/changes/" + cleanID); !strings.Contains(body, "Merges into main cleanly.") { | ||
| 1397 | 1397 | t.Fatalf("a mergeable branch was not reported as clean:\n%s", body) | |
| 1398 | 1398 | } | |
| 1399 | 1399 | ||
| @@ -1437,7 +1437,7 @@ func TestRequestPageSaysWhenItWouldConflict(t *testing.T) { | |||
| 1437 | 1437 | }, "ghost request"); err != nil { | |
| 1438 | 1438 | t.Fatalf("ghost request push: %v", err) | |
| 1439 | 1439 | } | |
| 1440 | if code, body := f.get("/r/" + f.repo + "/requests/" + ghostID); code != 200 || | ||
| 1440 | if code, body := f.get("/r/" + f.repo + "/changes/" + ghostID); code != 200 || | ||
| 1441 | 1441 | strings.Contains(body, "no longer merges") || strings.Contains(body, "Merges into main cleanly.") { | |
| 1442 | 1442 | t.Fatalf("the page claimed a merge result it could not compute (%d):\n%s", code, body) | |
| 1443 | 1443 | } | |
| @@ -1469,7 +1469,7 @@ func TestRequestDiscussionIsPushedAndOwned(t *testing.T) { | |||
| 1469 | 1469 | } | |
| 1470 | 1470 | ||
| 1471 | 1471 | // An empty discussion prints the command that fills it. | |
| 1472 | code, body := f.get("/r/" + f.repo + "/requests/" + reqID) | ||
| 1472 | code, body := f.get("/r/" + f.repo + "/changes/" + reqID) | ||
| 1473 | 1473 | if code != 200 { | |
| 1474 | 1474 | t.Fatalf("request page: %d", code) | |
| 1475 | 1475 | } | |
| @@ -1491,7 +1491,7 @@ func TestRequestDiscussionIsPushedAndOwned(t *testing.T) { | |||
| 1491 | 1491 | if len(cid) != 26 { | |
| 1492 | 1492 | t.Fatalf("no comment id printed: %q", out) | |
| 1493 | 1493 | } | |
| 1494 | _, body = f.get("/r/" + f.repo + "/requests/" + reqID) | ||
| 1494 | _, body = f.get("/r/" + f.repo + "/changes/" + reqID) | ||
| 1495 | 1495 | if !strings.Contains(body, "Looks good to me.") || !strings.Contains(body, `id="c-`+cid+`"`) { | |
| 1496 | 1496 | t.Fatalf("the comment is not rendered with an anchor:\n%s", body) | |
| 1497 | 1497 | } | |
| @@ -1508,7 +1508,7 @@ func TestRequestDiscussionIsPushedAndOwned(t *testing.T) { | |||
| 1508 | 1508 | if len(replyID) != 26 { | |
| 1509 | 1509 | t.Fatalf("no reply id printed: %q", replyOut) | |
| 1510 | 1510 | } | |
| 1511 | _, body = f.get("/r/" + f.repo + "/requests/" + reqID) | ||
| 1511 | _, body = f.get("/r/" + f.repo + "/changes/" + reqID) | ||
| 1512 | 1512 | if !strings.Contains(body, `class="comment-replies"`) || !strings.Contains(body, `id="c-`+replyID+`"`) || | |
| 1513 | 1513 | !strings.Contains(body, "A threaded reply.") { | |
| 1514 | 1514 | t.Fatalf("the CLI request reply is not nested:\n%s", body) | |
| @@ -1542,7 +1542,7 @@ func TestRequestDiscussionIsPushedAndOwned(t *testing.T) { | |||
| 1542 | 1542 | if err := other.apply(map[string]string{commentPath(wilburCm): commentFile("wilbur", created, "one question, rephrased\n")}, "edit own"); err != nil { | |
| 1543 | 1543 | t.Fatalf("editing your own comment was refused: %v", err) | |
| 1544 | 1544 | } | |
| 1545 | _, body = f.get("/r/" + f.repo + "/requests/" + reqID) | ||
| 1545 | _, body = f.get("/r/" + f.repo + "/changes/" + reqID) | ||
| 1546 | 1546 | if !strings.Contains(body, "one question, rephrased") || strings.Contains(body, "one question</") { | |
| 1547 | 1547 | t.Fatalf("the edited comment was not replaced:\n%s", body) | |
| 1548 | 1548 | } | |
| @@ -1558,7 +1558,7 @@ func TestRequestDiscussionIsPushedAndOwned(t *testing.T) { | |||
| 1558 | 1558 | if _, errs, err := f.cli(clone, "change", "rm-comment", reqID, cid); err != nil { | |
| 1559 | 1559 | t.Fatalf("delete parent comment: %v\n%s", err, errs) | |
| 1560 | 1560 | } | |
| 1561 | _, body = f.get("/r/" + f.repo + "/requests/" + reqID) | ||
| 1561 | _, body = f.get("/r/" + f.repo + "/changes/" + reqID) | ||
| 1562 | 1562 | if !strings.Contains(body, "Comment deleted") || !strings.Contains(body, "A threaded reply.") { | |
| 1563 | 1563 | t.Fatalf("the deleted request parent left no tombstone:\n%s", body) | |
| 1564 | 1564 | } | |
| @@ -1614,12 +1614,12 @@ func TestReviewCommentAnchorsALine(t *testing.T) { | |||
| 1614 | 1614 | } | |
| 1615 | 1615 | // The Files tab puts the comment beneath that line; the conversation still | |
| 1616 | 1616 | // labels the card with where it points. | |
| 1617 | _, body := f.get("/r/" + f.repo + "/requests/" + reqID + "/files/code.txt") | ||
| 1617 | _, body := f.get("/r/" + f.repo + "/changes/" + reqID + "/files/code.txt") | ||
| 1618 | 1618 | if !strings.Contains(body, `id="inline-c-`+newCm+`"`) || !strings.Contains(body, "#c-"+newCm) || | |
| 1619 | 1619 | !strings.Contains(body, "why FEATURE?") { | |
| 1620 | 1620 | t.Fatalf("the diff has no inline note for the comment:\n%s", body) | |
| 1621 | 1621 | } | |
| 1622 | _, body = f.get("/r/" + f.repo + "/requests/" + reqID) | ||
| 1622 | _, body = f.get("/r/" + f.repo + "/changes/" + reqID) | ||
| 1623 | 1623 | if !strings.Contains(body, "code.txt:2") || !strings.Contains(body, "(new side)") || | |
| 1624 | 1624 | !strings.Contains(body, `class="comment-snippet"`) || !strings.Contains(body, `class="snippet-line anchor"`) || | |
| 1625 | 1625 | !strings.Contains(body, "View in Files") { | |
| @@ -1675,12 +1675,12 @@ func TestReviewCommentAnchorsALine(t *testing.T) { | |||
| 1675 | 1675 | if _, errs, err := f.cli(clone, "change", "update", reqID, "--head", nextHead); err != nil { | |
| 1676 | 1676 | t.Fatalf("request update: %v\n%s", err, errs) | |
| 1677 | 1677 | } | |
| 1678 | _, body = f.get("/r/" + f.repo + "/requests/" + reqID) | ||
| 1678 | _, body = f.get("/r/" + f.repo + "/changes/" + reqID) | ||
| 1679 | 1679 | if !strings.Contains(body, "the file has changed since this comment") || | |
| 1680 | 1680 | !strings.Contains(body, `class="snippet-line anchor"`) || !strings.Contains(body, "original line") { | |
| 1681 | 1681 | t.Fatalf("a moved file did not keep the original snippet for the stale comment:\n%s", body) | |
| 1682 | 1682 | } | |
| 1683 | _, body = f.get("/r/" + f.repo + "/requests/" + reqID + "/files/code.txt") | ||
| 1683 | _, body = f.get("/r/" + f.repo + "/changes/" + reqID + "/files/code.txt") | ||
| 1684 | 1684 | if strings.Contains(body, `id="inline-c-`+newCm+`"`) { | |
| 1685 | 1685 | t.Fatalf("the stale comment kept its inline note:\n%s", body) | |
| 1686 | 1686 | } | |