исправлены находки ревью проектной стороны

- манифест читается так, как записан: решётка внутри строки не открывает
  комментарий, скобка внутри комментария не закрывает массив, имя внутри
  комментария не становится подпиской; новый ключ встаёт после массива,
  а не внутрь него
- всё записываемое проходит через manifest.Quote — обратный слэш в пути
  делал файл, который инструмент сам не читает
- маркер локальной части переехал в doc и пропускает огороженные блоки:
  процитированный в примере маркер больше не считается границей, а копия
  без маркера не перезаписывается молча
- лишний позиционный аргумент отсекается: flag прекращал разбор и прятал
  флаги после себя, из-за чего pull, list и check игнорировали --for
- заведены тесты проверок копий, включая молчание на исправной копии
This commit is contained in:
av
2026-07-27 21:16:29 +03:00
parent 23d88c4048
commit b6b0976c19
19 changed files with 904 additions and 197 deletions
+34 -3
View File
@@ -135,15 +135,46 @@ func insertionPoint(keys []string, at []int, key string, lines []string, start,
}
}
}
return at[len(at)-1] + 1
// The entry goes after the last key, and a key is not always one line: an
// array written down a column ends where its bracket closes. Appending
// after the first line of it would land the entry inside the array.
return valueEnd(lines, at[len(at)-1], end) + 1
}
// valueEnd returns the last line the value of a key occupies.
func valueEnd(lines []string, at, to int) int {
depth := 0
for n := at; n < to; n++ {
code, _ := splitComment(lines[n])
if n == at {
if i := strings.Index(code, "="); i >= 0 {
code = code[i+1:]
}
}
_, next, closeAt := scanCode(code, depth)
if closeAt >= 0 {
return n
}
if depth = next; depth <= 0 {
return n
}
}
return at
}
// renderEntry writes one key-value line, quoting the key when it is not bare.
func renderEntry(key, value string) string {
if !bareRe.MatchString(key) {
key = `"` + escape(key) + `"`
key = Quote(key)
}
return key + ` = "` + escape(value) + `"`
return key + " = " + Quote(value)
}
// Quote writes a string the way TOML reads it back. Every value the tool puts
// into a manifest goes through here: a Windows path is the ordinary case where
// a backslash left alone makes the tool unable to read the file it just wrote.
func Quote(s string) string {
return `"` + escape(s) + `"`
}
func escape(s string) string {