mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 22:14:25 +01:00
fix: keep co-author trailers in one trailer block
gstack-coauthor-trailers --message appended the new Co-authored-by lines as a separate paragraph after existing trailers, so git interpret-trailers (and GitHub attribution) read only the last paragraph and the existing co-author lost credit. The new lines now join the existing trailer block; the test checks the result with git interpret-trailers --parse. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
9ea5bfded5
commit
12d0463509
2 files changed
+11
-2
No files matched your search
@@ -77,8 +77,12 @@ function main(argv: string[]): number {
|
||||
const present = new Set([...text.matchAll(/^co-authored-by:.*<([^>]+)>\s*$/gim)].map(m => m[1]!.toLowerCase()));
|
||||
appended = [...authors.entries()].filter(([key]) => !present.has(key)).map(([, a]) => `Co-authored-by: ${a.name} <${a.email}>`);
|
||||
if (appended.length) {
|
||||
// Trailers are one paragraph: a blank line before the new ones would make git (and GitHub's
|
||||
// attribution) read only the last paragraph as the trailer block and drop the existing co-authors.
|
||||
const body = text.replace(/\s+$/, '');
|
||||
fs.writeFileSync(message, (body ? body + '\n\n' : '') + appended.join('\n') + '\n');
|
||||
const cut = body.lastIndexOf('\n\n');
|
||||
const endsInTrailer = cut >= 0 && body.slice(cut + 2).split('\n').every(l => /^[A-Za-z][\w-]*: \S/.test(l));
|
||||
fs.writeFileSync(message, (body ? body + (endsInTrailer ? '\n' : '\n\n') : '') + appended.join('\n') + '\n');
|
||||
}
|
||||
}
|
||||
if (argv.includes('--json')) process.stdout.write(JSON.stringify({ range, authors: [...authors.values()], trailers, appended }) + '\n');
|
||||
|
||||
@@ -72,8 +72,13 @@ test('--message appends only the missing trailers and is idempotent; a bad range
|
||||
const file = path.join(dir, 'MSG');
|
||||
fs.writeFileSync(file, 'port: contributor fix\n\nCo-authored-by: ada contributor <ADA@example.org>\n');
|
||||
expect(run(dir, ['--message', file]).status).toBe(EXIT.ok);
|
||||
const expected = 'port: contributor fix\n\nCo-authored-by: ada contributor <ADA@example.org>\n\nCo-authored-by: Bo Helper <bo@example.org>\n';
|
||||
const expected = 'port: contributor fix\n\nCo-authored-by: ada contributor <ADA@example.org>\nCo-authored-by: Bo Helper <bo@example.org>\n';
|
||||
expect(fs.readFileSync(file, 'utf8')).toBe(expected);
|
||||
expect(spawnSync('git', ['interpret-trailers', '--parse'], { cwd: dir, input: expected, encoding: 'utf8' }).stdout.trim().split('\n')).toHaveLength(2);
|
||||
const plain = path.join(dir, 'PLAIN');
|
||||
fs.writeFileSync(plain, 'port: contributor fix\n');
|
||||
expect(run(dir, ['--message', plain]).status).toBe(EXIT.ok);
|
||||
expect(fs.readFileSync(plain, 'utf8')).toBe('port: contributor fix\n\nCo-authored-by: Ada Contributor <Ada@Example.org>\nCo-authored-by: Bo Helper <bo@example.org>\n');
|
||||
const again = run(dir, ['--message', file, '--json']);
|
||||
expect(JSON.parse(again.stdout).appended).toEqual([]);
|
||||
expect(fs.readFileSync(file, 'utf8')).toBe(expected);
|
||||
|
||||
Reference in new issue
Block a user