Skip to content

Commit 2dd364d

Browse files
committed
bugfix-319-setup-crash-on-repository-with-no-issues: Refactor content extraction and update logic to use indexOf with a starting offset for end tags, removing the custom findExactMatch method.
1 parent 9326ccd commit 2dd364d

6 files changed

Lines changed: 82 additions & 70 deletions

File tree

build/cli/index.js

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52775,20 +52775,24 @@ class ContentInterface {
5277552775
if (description === undefined) {
5277652776
return undefined;
5277752777
}
52778-
const startIndex = this.findExactMatch(description, this.startPattern);
52779-
const endIndex = this.findExactMatch(description, this.endPattern);
52780-
if (startIndex === -1 || endIndex === -1) {
52778+
const startIndex = description.indexOf(this.startPattern);
52779+
if (startIndex === -1) {
5278152780
return undefined;
5278252781
}
52783-
return description.substring(startIndex + this.startPattern.length, endIndex);
52782+
const contentStart = startIndex + this.startPattern.length;
52783+
const endIndex = description.indexOf(this.endPattern, contentStart);
52784+
if (endIndex === -1) {
52785+
return undefined;
52786+
}
52787+
return description.substring(contentStart, endIndex);
5278452788
}
5278552789
catch (error) {
5278652790
(0, logger_1.logError)(`Error reading issue configuration: ${error}`);
5278752791
throw error;
5278852792
}
5278952793
};
5279052794
this._addContent = (description, content) => {
52791-
if (this.findExactMatch(description, this.startPattern) === -1 && this.findExactMatch(description, this.endPattern) === -1) {
52795+
if (description.indexOf(this.startPattern) === -1 && description.indexOf(this.endPattern) === -1) {
5279252796
const newContent = `${this.startPattern}\n${content}\n${this.endPattern}`;
5279352797
return `${description}\n\n${newContent}`;
5279452798
}
@@ -52797,9 +52801,14 @@ class ContentInterface {
5279752801
}
5279852802
};
5279952803
this._updateContent = (description, content) => {
52800-
const startIndex = this.findExactMatch(description, this.startPattern);
52801-
const endIndex = this.findExactMatch(description, this.endPattern);
52802-
if (startIndex === -1 || endIndex === -1) {
52804+
const startIndex = description.indexOf(this.startPattern);
52805+
if (startIndex === -1) {
52806+
(0, logger_1.logError)(`The content has a problem with open-close tags: ${this.startPattern} / ${this.endPattern}`);
52807+
return undefined;
52808+
}
52809+
const contentStart = startIndex + this.startPattern.length;
52810+
const endIndex = description.indexOf(this.endPattern, contentStart);
52811+
if (endIndex === -1) {
5280352812
(0, logger_1.logError)(`The content has a problem with open-close tags: ${this.startPattern} / ${this.endPattern}`);
5280452813
return undefined;
5280552814
}
@@ -52840,19 +52849,6 @@ class ContentInterface {
5284052849
}
5284152850
return `${this._id}-end -->`;
5284252851
}
52843-
findExactMatch(description, pattern) {
52844-
let index = 0;
52845-
while ((index = description.indexOf(pattern, index)) !== -1) {
52846-
const nextChar = description[index + pattern.length];
52847-
// If the next character is alphanumeric or a hyphen, it's a partial match (e.g., "-starts-here")
52848-
// So we skip it. Otherwise, it's an exact match.
52849-
if (!nextChar || !/[a-zA-Z0-9-]/.test(nextChar)) {
52850-
return index;
52851-
}
52852-
index += pattern.length;
52853-
}
52854-
return -1;
52855-
}
5285652852
}
5285752853
exports.ContentInterface = ContentInterface;
5285852854

build/cli/src/manager/description/base/content_interface.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ export declare abstract class ContentInterface {
44
abstract get visibleContent(): boolean;
55
private get startPattern();
66
private get endPattern();
7-
private findExactMatch;
87
getContent: (description: string | undefined) => string | undefined;
98
private _addContent;
109
private _updateContent;

build/github_action/index.js

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47856,20 +47856,24 @@ class ContentInterface {
4785647856
if (description === undefined) {
4785747857
return undefined;
4785847858
}
47859-
const startIndex = this.findExactMatch(description, this.startPattern);
47860-
const endIndex = this.findExactMatch(description, this.endPattern);
47861-
if (startIndex === -1 || endIndex === -1) {
47859+
const startIndex = description.indexOf(this.startPattern);
47860+
if (startIndex === -1) {
4786247861
return undefined;
4786347862
}
47864-
return description.substring(startIndex + this.startPattern.length, endIndex);
47863+
const contentStart = startIndex + this.startPattern.length;
47864+
const endIndex = description.indexOf(this.endPattern, contentStart);
47865+
if (endIndex === -1) {
47866+
return undefined;
47867+
}
47868+
return description.substring(contentStart, endIndex);
4786547869
}
4786647870
catch (error) {
4786747871
(0, logger_1.logError)(`Error reading issue configuration: ${error}`);
4786847872
throw error;
4786947873
}
4787047874
};
4787147875
this._addContent = (description, content) => {
47872-
if (this.findExactMatch(description, this.startPattern) === -1 && this.findExactMatch(description, this.endPattern) === -1) {
47876+
if (description.indexOf(this.startPattern) === -1 && description.indexOf(this.endPattern) === -1) {
4787347877
const newContent = `${this.startPattern}\n${content}\n${this.endPattern}`;
4787447878
return `${description}\n\n${newContent}`;
4787547879
}
@@ -47878,9 +47882,14 @@ class ContentInterface {
4787847882
}
4787947883
};
4788047884
this._updateContent = (description, content) => {
47881-
const startIndex = this.findExactMatch(description, this.startPattern);
47882-
const endIndex = this.findExactMatch(description, this.endPattern);
47883-
if (startIndex === -1 || endIndex === -1) {
47885+
const startIndex = description.indexOf(this.startPattern);
47886+
if (startIndex === -1) {
47887+
(0, logger_1.logError)(`The content has a problem with open-close tags: ${this.startPattern} / ${this.endPattern}`);
47888+
return undefined;
47889+
}
47890+
const contentStart = startIndex + this.startPattern.length;
47891+
const endIndex = description.indexOf(this.endPattern, contentStart);
47892+
if (endIndex === -1) {
4788447893
(0, logger_1.logError)(`The content has a problem with open-close tags: ${this.startPattern} / ${this.endPattern}`);
4788547894
return undefined;
4788647895
}
@@ -47921,19 +47930,6 @@ class ContentInterface {
4792147930
}
4792247931
return `${this._id}-end -->`;
4792347932
}
47924-
findExactMatch(description, pattern) {
47925-
let index = 0;
47926-
while ((index = description.indexOf(pattern, index)) !== -1) {
47927-
const nextChar = description[index + pattern.length];
47928-
// If the next character is alphanumeric or a hyphen, it's a partial match (e.g., "-starts-here")
47929-
// So we skip it. Otherwise, it's an exact match.
47930-
if (!nextChar || !/[a-zA-Z0-9-]/.test(nextChar)) {
47931-
return index;
47932-
}
47933-
index += pattern.length;
47934-
}
47935-
return -1;
47936-
}
4793747933
}
4793847934
exports.ContentInterface = ContentInterface;
4793947935

build/github_action/src/manager/description/base/content_interface.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ export declare abstract class ContentInterface {
44
abstract get visibleContent(): boolean;
55
private get startPattern();
66
private get endPattern();
7-
private findExactMatch;
87
getContent: (description: string | undefined) => string | undefined;
98
private _addContent;
109
private _updateContent;

src/manager/description/base/__tests__/content_interface.test.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,18 @@ describe('ContentInterface', () => {
166166
expect(handler.getContent(desc)).toBe('\n{"valid":"true"}\n');
167167
});
168168

169-
it('ignores partial matches of start or end tags', () => {
170-
const desc = `<!-- copilot-config-starts-here \n${start}\n{"some":"data"}\n${end}\n copilot-config-end-here -->`;
171-
expect(handler.getContent(desc)).toBe('\n{"some":"data"}\n');
169+
it('returns empty string when there is no content between tags', () => {
170+
const desc = `pre\n${start}${end}\npost`;
171+
expect(handler.getContent(desc)).toBe('');
172+
});
173+
174+
it('returns undefined when tags are inverted (end appears before start)', () => {
175+
const desc = `pre\n${end}\nsome content\n${start}\npost`;
176+
expect(handler.getContent(desc)).toBeUndefined();
177+
});
178+
179+
it('returns undefined for an empty description string', () => {
180+
expect(handler.getContent('')).toBeUndefined();
172181
});
173182
});
174183

@@ -208,7 +217,25 @@ describe('ContentInterface', () => {
208217
const result = handler.updateContent(desc, 'new');
209218
expect(result).toBe(`pre\r\n${start}\nnew\n${end}\r\npost`);
210219
});
211-
});
212220

221+
it('returns undefined when description is empty string (should append)', () => {
222+
const desc = '';
223+
const result = handler.updateContent(desc, 'new');
224+
expect(result).toBe(`\n\n${start}\nnew\n${end}`);
225+
});
226+
227+
it('correctly updates even when substituting with empty content', () => {
228+
const desc = `pre\n${start}\nold\n${end}\npost`;
229+
const result = handler.updateContent(desc, '');
230+
expect(result).toBe(`pre\n${start}\n\n${end}\npost`);
231+
});
232+
233+
it('correctly updates when new content contains tag-like strings', () => {
234+
const desc = `pre\n${start}\nold\n${end}\npost`;
235+
const tagLikeContent = `{"fakeStart": "${start}"}`;
236+
const result = handler.updateContent(desc, tagLikeContent);
237+
expect(result).toBe(`pre\n${start}\n${tagLikeContent}\n${end}\npost`);
238+
});
239+
});
213240
});
214241
});

src/manager/description/base/content_interface.ts

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,40 +23,30 @@ export abstract class ContentInterface {
2323
return `${this._id}-end -->`
2424
}
2525

26-
private findExactMatch(description: string, pattern: string): number {
27-
let index = 0;
28-
while ((index = description.indexOf(pattern, index)) !== -1) {
29-
const nextChar = description[index + pattern.length];
30-
// If the next character is alphanumeric or a hyphen, it's a partial match (e.g., "-starts-here")
31-
// So we skip it. Otherwise, it's an exact match.
32-
if (!nextChar || !/[a-zA-Z0-9-]/.test(nextChar)) {
33-
return index;
34-
}
35-
index += pattern.length;
36-
}
37-
return -1;
38-
}
39-
4026
getContent = (description: string | undefined): string | undefined => {
4127
try {
4228
if (description === undefined) {
4329
return undefined;
4430
}
45-
const startIndex = this.findExactMatch(description, this.startPattern);
46-
const endIndex = this.findExactMatch(description, this.endPattern);
47-
if (startIndex === -1 || endIndex === -1) {
31+
const startIndex = description.indexOf(this.startPattern);
32+
if (startIndex === -1) {
33+
return undefined;
34+
}
35+
const contentStart = startIndex + this.startPattern.length;
36+
const endIndex = description.indexOf(this.endPattern, contentStart);
37+
if (endIndex === -1) {
4838
return undefined;
4939
}
5040

51-
return description.substring(startIndex + this.startPattern.length, endIndex);
41+
return description.substring(contentStart, endIndex);
5242
} catch (error) {
5343
logError(`Error reading issue configuration: ${error}`);
5444
throw error;
5545
}
5646
}
5747

5848
private _addContent = (description: string, content: string) => {
59-
if (this.findExactMatch(description, this.startPattern) === -1 && this.findExactMatch(description, this.endPattern) === -1) {
49+
if (description.indexOf(this.startPattern) === -1 && description.indexOf(this.endPattern) === -1) {
6050
const newContent = `${this.startPattern}\n${content}\n${this.endPattern}`;
6151
return `${description}\n\n${newContent}`;
6252
} else {
@@ -65,9 +55,14 @@ export abstract class ContentInterface {
6555
}
6656

6757
private _updateContent = (description: string, content: string) => {
68-
const startIndex = this.findExactMatch(description, this.startPattern);
69-
const endIndex = this.findExactMatch(description, this.endPattern);
70-
if (startIndex === -1 || endIndex === -1) {
58+
const startIndex = description.indexOf(this.startPattern);
59+
if (startIndex === -1) {
60+
logError(`The content has a problem with open-close tags: ${this.startPattern} / ${this.endPattern}`);
61+
return undefined;
62+
}
63+
const contentStart = startIndex + this.startPattern.length;
64+
const endIndex = description.indexOf(this.endPattern, contentStart);
65+
if (endIndex === -1) {
7166
logError(`The content has a problem with open-close tags: ${this.startPattern} / ${this.endPattern}`);
7267
return undefined;
7368
}

0 commit comments

Comments
 (0)