Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: match and update maxRevision entries with decoded keys #458

Merged
merged 7 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/shared/populateFilePaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ export const populateFilePaths = (elements: ChangeResult[], packageDirPaths: str
matchingComponent.xml
} and maybe ${matchingComponent.walkContent().toString()}`
);
const key = getMetadataKey(matchingComponent.type.name, matchingComponent.fullName);
// Decode the key since local components can have encoded fullNames, but results from querying
// SourceMembers have fullNames that are not encoded. See: https://github.com/forcedotcom/cli/issues/1683
const key = decodeURI(getMetadataKey(matchingComponent.type.name, matchingComponent.fullName));
elementMap.set(key, {
...elementMap.get(key),
modified: true,
Expand Down
31 changes: 29 additions & 2 deletions src/shared/remoteSourceTrackingService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -500,11 +500,38 @@ export class RemoteSourceTrackingService extends ConfigFile<RemoteSourceTracking

// Return a tracked element as MemberRevision data.
private getSourceMember(key: string): Optional<MemberRevision> {
return this.getSourceMembers()[key];
const sourceMembers = this.getSourceMembers();
let sm = sourceMembers[key];
if (!sm) {
// Get all SourceMember keys in maxRevision, then iterate over them
// and compare their decoded value with the decoded key.
Object.keys(sourceMembers).some((memberKey) => {
shetzel marked this conversation as resolved.
Show resolved Hide resolved
if (decodeURI(memberKey) === decodeURI(key)) {
sm = sourceMembers[memberKey];
this.logger.debug(`${key} matches already tracked member: ${memberKey}`);
return true;
}
});
}
return sm;
}

private setMemberRevision(key: string, sourceMember: MemberRevision): void {
this.getContents().sourceMembers[key] = sourceMember;
const sourceMembers = this.getSourceMembers();
const sm = sourceMembers[key];
let matchingKey = key;
if (!sm) {
// Get all SourceMember keys in maxRevision, then iterate over them
// and compare their decoded value with the decoded key.
Object.keys(sourceMembers).some((memberKey) => {
if (decodeURI(memberKey) === decodeURI(key)) {
matchingKey = memberKey;
this.logger.debug(`${key} matches already tracked member: ${memberKey}`);
return true;
}
});
}
this.getContents().sourceMembers[matchingKey] = sourceMember;
}

private calculateTimeout(memberCount: number): Duration {
Expand Down
148 changes: 148 additions & 0 deletions test/unit/remoteSourceTracking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,154 @@ describe('remoteSourceTrackingService', () => {
deleted: true,
});
});

it('will match decoded SourceMember keys on get', async () => {
const maxJson = {
serverMaxRevisionCounter: 2,
sourceMembers: {
'Layout__Broker__c-Broker Layout': {
serverRevisionCounter: 1,
lastRetrievedFromServer: 1,
memberType: 'Layout',
isNameObsolete: false,
},
'Layout__Broker__c-v1.1 Broker Layout': {
serverRevisionCounter: 2,
lastRetrievedFromServer: 2,
memberType: 'Layout',
isNameObsolete: false,
},
},
};
await remoteSourceTrackingService.setContentsFromObject(maxJson);

// @ts-ignore getSourceMember is private
expect(remoteSourceTrackingService.getSourceMember('Layout__Broker__c-v1%2E1 Broker Layout')).to.deep.equal({
serverRevisionCounter: 2,
lastRetrievedFromServer: 2,
memberType: 'Layout',
isNameObsolete: false,
});
});

it('will match encoded SourceMember keys on get', async () => {
const maxJson = {
serverMaxRevisionCounter: 2,
sourceMembers: {
'Layout__Broker__c-Broker Layout': {
serverRevisionCounter: 1,
lastRetrievedFromServer: 1,
memberType: 'Layout',
isNameObsolete: false,
},
'Layout__Broker__c-v1%2E1 Broker Layout': {
serverRevisionCounter: 2,
lastRetrievedFromServer: 2,
memberType: 'Layout',
isNameObsolete: false,
},
},
};
await remoteSourceTrackingService.setContentsFromObject(maxJson);

// @ts-ignore getSourceMember is private
expect(remoteSourceTrackingService.getSourceMember('Layout__Broker__c-v1.1 Broker Layout')).to.deep.equal({
serverRevisionCounter: 2,
lastRetrievedFromServer: 2,
memberType: 'Layout',
isNameObsolete: false,
});
});

it('will match/update decoded SourceMember keys on set', async () => {
const maxJson = {
serverMaxRevisionCounter: 2,
sourceMembers: {
'Layout__Broker__c-Broker Layout': {
serverRevisionCounter: 1,
lastRetrievedFromServer: 1,
memberType: 'Layout',
isNameObsolete: false,
},
'Layout__Broker__c-v1.1 Broker Layout': {
serverRevisionCounter: 2,
lastRetrievedFromServer: 2,
memberType: 'Layout',
isNameObsolete: false,
},
},
};
await remoteSourceTrackingService.setContentsFromObject(maxJson);

// @ts-ignore setMemberRevision is private
remoteSourceTrackingService.setMemberRevision('Layout__Broker__c-v1%2E1 Broker Layout', {
serverRevisionCounter: 3,
lastRetrievedFromServer: 3,
memberType: 'Layout',
isNameObsolete: false,
});

// @ts-ignore getSourceMembers is private
expect(remoteSourceTrackingService.getSourceMembers()).to.deep.equal({
'Layout__Broker__c-Broker Layout': {
serverRevisionCounter: 1,
lastRetrievedFromServer: 1,
memberType: 'Layout',
isNameObsolete: false,
},
'Layout__Broker__c-v1.1 Broker Layout': {
serverRevisionCounter: 3,
lastRetrievedFromServer: 3,
memberType: 'Layout',
isNameObsolete: false,
},
});
});

it('will match/update encoded SourceMember keys on set', async () => {
const maxJson = {
serverMaxRevisionCounter: 2,
sourceMembers: {
'Layout__Broker__c-Broker Layout': {
serverRevisionCounter: 1,
lastRetrievedFromServer: 1,
memberType: 'Layout',
isNameObsolete: false,
},
'Layout__Broker__c-v1%2E1 Broker Layout': {
serverRevisionCounter: 2,
lastRetrievedFromServer: 2,
memberType: 'Layout',
isNameObsolete: false,
},
},
};
await remoteSourceTrackingService.setContentsFromObject(maxJson);

// @ts-ignore setMemberRevision is private
remoteSourceTrackingService.setMemberRevision('Layout__Broker__c-v1.1 Broker Layout', {
serverRevisionCounter: 3,
lastRetrievedFromServer: 3,
memberType: 'Layout',
isNameObsolete: false,
});

// @ts-ignore getSourceMembers is private
expect(remoteSourceTrackingService.getSourceMembers()).to.deep.equal({
'Layout__Broker__c-Broker Layout': {
serverRevisionCounter: 1,
lastRetrievedFromServer: 1,
memberType: 'Layout',
isNameObsolete: false,
},
'Layout__Broker__c-v1%2E1 Broker Layout': {
serverRevisionCounter: 3,
lastRetrievedFromServer: 3,
memberType: 'Layout',
isNameObsolete: false,
},
});
});
});

describe('setServerMaxRevision', () => {
Expand Down