Let a commit copy files from another forge repository, so a large move is not typed through the caller
mesh/merge-gate head dc3a177410fa merged into trunk c0880c4dc271 — pass: builds gitea → novox; no bus step; every machine composes with the change as it di…
mesh/repo-check head dc3a177410fa merged into trunk c0880c4dc271 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered

This commit is contained in:
2026-10-20 01:07:28 +00:00
parent c0880c4dc2
commit dc3a177410
6 changed files with 611 additions and 5 deletions
+28 -3
View File
@@ -25,6 +25,8 @@ type FileChange struct {
Content *string
ContentBase64 *string
Delete bool
CopyFrom *CopyFrom // copy_from (novox/hq issue 1365): the content of a file or directory of another repository
size int // the content's size in bytes, as committed
}
// CommitAsk is one gitea_commit call.
@@ -51,6 +53,7 @@ type Committed struct {
Parent string `json:"parent"`
Commit string `json:"commit"`
Files []CommittedFile `json:"files,omitempty"`
Copies []CopiedFrom `json:"copies,omitempty"`
Said []string `json:"said"`
}
@@ -118,6 +121,16 @@ func readCommitAsk(args map[string]any) (CommitAsk, error) {
}
fc.Delete = b
}
if v, ok := m["copy_from"]; ok && v != nil {
c, err := readCopyFrom(i, v)
if err != nil {
return a, err
}
fc.CopyFrom = c
if fc.Content != nil || fc.ContentBase64 != nil || fc.Delete {
return a, refuse("files[%d] (%s) gives copy_from together with content, content_base64 or delete: it takes exactly one of them. Nothing was sent", i, fc.Path)
}
}
a.Files = append(a.Files, fc)
}
}
@@ -157,13 +170,13 @@ func readCommitAsk(args map[string]any) (CommitAsk, error) {
}
seen[fc.Path] = true
have := 0
for _, g := range []bool{fc.Content != nil, fc.ContentBase64 != nil, fc.Delete} {
for _, g := range []bool{fc.Content != nil, fc.ContentBase64 != nil, fc.Delete, fc.CopyFrom != nil} {
if g {
have++
}
}
if have != 1 {
return a, refuse("files[%d] (%s) needs exactly one of content, content_base64 or delete: true. Nothing was sent", i, fc.Path)
return a, refuse("files[%d] (%s) needs exactly one of content, content_base64, delete: true or copy_from. Nothing was sent", i, fc.Path)
}
if fc.Content != nil && !utf8.ValidString(*fc.Content) {
return a, refuse("files[%d].content (%s) is not UTF-8 text: give it as content_base64. Nothing was sent", i, fc.Path)
@@ -186,6 +199,7 @@ func readCommitAsk(args map[string]any) (CommitAsk, error) {
if size > maxFileBytes {
return a, refuse("files[%d] (%s) is %s, more than the %s one file of a commit may be. Nothing was sent", i, fc.Path, mib(size), mib(maxFileBytes))
}
a.Files[i].size = size
total += size
}
if total > maxCommitBytes {
@@ -318,8 +332,19 @@ func commit(ctx context.Context, f *Forge, a CommitAsk) (*Committed, error) {
return nil, fmt.Errorf("the forge did not take the patch: %w", err)
}
} else {
var ops []map[string]any
files := a.Files
for _, fc := range a.Files {
if fc.CopyFrom != nil {
// Read, and judged against the limits, before anything is sent.
var err error
if files, out.Copies, err = expandCopies(ctx, f, a); err != nil {
return nil, err
}
break
}
}
var ops []map[string]any
for _, fc := range files {
sha, err := f.blobAt(ctx, repo, fc.Path, ref)
if err != nil {
return nil, err