mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 19:11:25 +01:00
feat(repo): sync forks on the server, wire forks into clones, validate set-default
repo sync OWNER/REPO, run where no Git remote points to the repository,
now updates it on the server: a fork's branch fast-forwards to its
parent's through merge-upstream, and a pull mirror fetches its source.
repo fork reports an existing fork ("! bob/x already exists") instead of
a raw HTTP 409, refuses to fork a repository into its own owner, and
gains --fork-name, --clone (Git flags after --) and --remote, which adds
the fork as origin and renames the old origin to upstream.
repo clone passes Git flags after --, and takes --upstream-remote-name
and --no-upstream for forks. Clones report what they set up.
repo set-default checks that the repository exists before saving it,
prints the saved repository with --view, removes it with --unset, and
reports the change.
Signed-off-by: bircni <bircni@icloud.com>
This commit is contained in:
13 files changed
+599
-98
No files matched your search
@@ -159,6 +159,67 @@ func TestRenamedURL(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepoForkReportsAnExistingFork(t *testing.T) {
|
||||
var requests []string
|
||||
server := newAuthenticatedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
requests = append(requests, r.Method+" "+r.URL.Path)
|
||||
switch r.Method + " " + r.URL.Path {
|
||||
case "POST /api/v1/repos/bob/project/forks":
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
_, _ = w.Write([]byte(`{"message":"repository is already forked by user [uname: alice, repo path: bob/project, fork path: alice/project-fork]"}`))
|
||||
case "GET /api/v1/repos/bob/project/forks":
|
||||
if r.URL.Query().Get("page") != "1" {
|
||||
_, _ = w.Write([]byte(`[]`))
|
||||
return
|
||||
}
|
||||
_, _ = w.Write([]byte(`[{"full_name":"carol/project","owner":{"login":"carol"}},{"full_name":"alice/project-fork","owner":{"login":"alice"}}]`))
|
||||
case "GET /api/v1/repos/alice/project-fork":
|
||||
_, _ = w.Write([]byte(`{"full_name":"alice/project-fork","fork":true,"html_url":"https://gitea.test/alice/project-fork","parent":{"full_name":"bob/project"}}`))
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
deps, out, diagnostics := repoTTYDeps(t, server.URL)
|
||||
require.NoError(t, Execute(context.Background(), deps, []string{"repo", "fork", "bob/project"}))
|
||||
require.Equal(t, "! alice/project-fork already exists\n", diagnostics.String())
|
||||
require.Equal(t, "https://gitea.test/alice/project-fork\n", out.String())
|
||||
require.Equal(t, "GET /api/v1/repos/alice/project-fork", requests[len(requests)-1])
|
||||
}
|
||||
|
||||
func TestRepoForkRefusesTheOwnersRepository(t *testing.T) {
|
||||
server := newAuthenticatedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("unexpected request %s %s", r.Method, r.URL.Path)
|
||||
}))
|
||||
defer server.Close()
|
||||
deps, _, _ := serverDeps(t, server.URL)
|
||||
err := Execute(context.Background(), deps, []string{"repo", "fork", "alice/project"})
|
||||
require.Equal(t, clierr.Usage, clierr.ExitCode(err), "%v", err)
|
||||
require.ErrorContains(t, err, "cannot fork alice/project into alice: it already owns it; pass --org")
|
||||
}
|
||||
|
||||
func TestRepoForkAddsTheForkAsOrigin(t *testing.T) {
|
||||
server := newAuthenticatedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, "POST /api/v1/repos/bob/project/forks", r.Method+" "+r.URL.Path)
|
||||
requirePayload(t, `{"name":"mine"}`, r.Body)
|
||||
_, _ = fmt.Fprintf(w, `{"full_name":"alice/mine","html_url":"https://gitea.test/alice/mine","clone_url":"http://%s/alice/mine.git"}`, r.Host)
|
||||
}))
|
||||
defer server.Close()
|
||||
deps, out, diagnostics := repoTTYDeps(t, server.URL)
|
||||
fork := server.URL + "/alice/mine.git"
|
||||
runner := &fakeGit{results: map[string]string{
|
||||
"rev-parse --is-inside-work-tree": "true",
|
||||
"remote get-url origin": server.URL + "/bob/project.git",
|
||||
"remote rename origin upstream": "",
|
||||
"remote add -- origin " + fork: "",
|
||||
}}
|
||||
deps.Git = runner
|
||||
require.NoError(t, Execute(context.Background(), deps, []string{"repo", "fork", "bob/project", "--fork-name", "mine", "--remote"}))
|
||||
require.Equal(t, []string{"rev-parse --is-inside-work-tree", "remote get-url origin", "remote rename origin upstream", "remote add -- origin " + fork}, runner.calls)
|
||||
require.Equal(t, "✓ Forked bob/project to alice/mine\n✓ Renamed Git remote origin to upstream\n✓ Added Git remote origin for alice/mine\n", diagnostics.String())
|
||||
require.Equal(t, "https://gitea.test/alice/mine\n", out.String())
|
||||
}
|
||||
|
||||
func TestRepoDeleteReportsTheDeletion(t *testing.T) {
|
||||
server := newAuthenticatedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, http.MethodDelete+" /api/v1/repos/alice/x", r.Method+" "+r.URL.Path)
|
||||
|
||||
Reference in new issue
Block a user