Skip to content

Commit c761737

Browse files
authored
Merge pull request #1475 from ebkr/immutable-profile-pt5-profileinstallprovider-mode
Refactor ProfileInstallerProvider to use ImmutableProfile when enabling/disabling mods
2 parents 9eec207 + c724da7 commit c761737

File tree

8 files changed

+39
-74
lines changed

8 files changed

+39
-74
lines changed

src/components/profiles-modals/ImportProfileModal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ export default class ImportProfileModal extends mixins(ProfilesMixin) {
260260
await ProfileModList.updateMod(installedMod, this.activeProfile.asImmutableProfile(), async (modToDisable: ManifestV2) => {
261261
// Need to enable temporarily so the manager doesn't think it's re-disabling a disabled mod.
262262
modToDisable.enable();
263-
await ProfileInstallerProvider.instance.disableMod(modToDisable, this.activeProfile);
263+
await ProfileInstallerProvider.instance.disableMod(modToDisable, this.activeProfile.asImmutableProfile());
264264
modToDisable.disable();
265265
});
266266
}

src/components/views/DownloadModModal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ let assignId = 0;
425425
await ProfileModList.updateMod(manifestMod, profile.asImmutableProfile(), async mod => {
426426
mod.disable();
427427
});
428-
await ProfileInstallerProvider.instance.disableMod(manifestMod, profile);
428+
await ProfileInstallerProvider.instance.disableMod(manifestMod, profile.asImmutableProfile());
429429
}
430430
}
431431
}

src/providers/generic/installing/ConflictManagementProvider.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import ProviderUtils from '../../generic/ProviderUtils';
22
import ManifestV2 from '../../../model/ManifestV2';
33
import R2Error from '../../../model/errors/R2Error';
4-
import Profile from '../../../model/Profile';
4+
import Profile, { ImmutableProfile } from '../../../model/Profile';
55

66
export default abstract class ConflictManagementProvider {
77

@@ -22,7 +22,7 @@ export default abstract class ConflictManagementProvider {
2222

2323
public abstract overrideInstalledState(mod: ManifestV2, profile: Profile): Promise<R2Error | void>;
2424

25-
public abstract isFileActive(mod: ManifestV2, profile: Profile, file: string): Promise<boolean>;
25+
public abstract isFileActive(mod: ManifestV2, profile: Profile|ImmutableProfile, file: string): Promise<boolean>;
2626

2727
}
2828

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import ProviderUtils from '../../generic/ProviderUtils';
22
import ManifestV2 from '../../../model/ManifestV2';
33
import R2Error from '../../../model/errors/R2Error';
4-
import FileTree from '../../../model/file/FileTree';
5-
import Profile from '../../../model/Profile';
4+
import Profile, { ImmutableProfile } from '../../../model/Profile';
65

76
export default abstract class ProfileInstallerProvider {
87

@@ -28,37 +27,17 @@ export default abstract class ProfileInstallerProvider {
2827
* Disable files to prevent the mod from loading.
2928
* @param mod
3029
*/
31-
public abstract disableMod(mod: ManifestV2, profile: Profile): Promise<R2Error | void>;
30+
public abstract disableMod(mod: ManifestV2, profile: ImmutableProfile): Promise<R2Error | void>;
3231

3332
/**
3433
* Enable files to undo a disable operation.
3534
* @param mod
3635
*/
37-
public abstract enableMod(mod: ManifestV2, profile: Profile): Promise<R2Error | void>;
36+
public abstract enableMod(mod: ManifestV2, profile: ImmutableProfile): Promise<R2Error | void>;
3837

3938
/**
4039
* Installs a mod to the profile.
4140
* @param mod
4241
*/
4342
public abstract installMod(mod: ManifestV2, profile: Profile): Promise<R2Error | null>;
44-
45-
/**
46-
* Applies either enabling or disabling under a shared method.
47-
* Logic for both {@method enableMod} and {@method disableMod} should be handled here.
48-
*
49-
* @param mod
50-
* @param tree A BepInExTree object to provide a list of all files provided in the mod.
51-
* @param location The location of the mod within a BepInEx sub-folder.
52-
* @param mode The ModMode number. {@class model/enums/ModMode}
53-
*/
54-
abstract applyModMode(mod: ManifestV2, tree: FileTree, profile: Profile, location: string, mode: number): Promise<R2Error | void>;
55-
56-
/**
57-
* Get descendant files of a given location.
58-
*
59-
* For params, see {@method applyModMode}
60-
* @param tree If tree is not provided, one is created on first call. This method is recursive.
61-
* @param location
62-
*/
63-
abstract getDescendantFiles(tree: FileTree | null, location: string): Promise<string[]>;
6443
}

src/r2mm/installing/ConflictManagementProviderImpl.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as path from 'path';
66
import yaml from 'yaml';
77
import ModFileTracker from '../../model/installing/ModFileTracker';
88
import StateTracker from '../../model/installing/StateTracker';
9-
import Profile from '../../model/Profile';
9+
import Profile, { ImmutableProfile } from '../../model/Profile';
1010
import FileUtils from '../../utils/FileUtils';
1111

1212
export default class ConflictManagementProviderImpl extends ConflictManagementProvider {
@@ -98,7 +98,7 @@ export default class ConflictManagementProviderImpl extends ConflictManagementPr
9898
} as StateTracker));
9999
}
100100

101-
public async isFileActive(mod: ManifestV2, profile: Profile, file: string) {
101+
public async isFileActive(mod: ManifestV2, profile: Profile|ImmutableProfile, file: string) {
102102
const state = await this.getTotalState(profile);
103103
for (const [stateFile, stateMod] of state.currentState) {
104104
if (stateFile === file) {
@@ -108,7 +108,7 @@ export default class ConflictManagementProviderImpl extends ConflictManagementPr
108108
return false;
109109
}
110110

111-
private async getTotalState(profile: Profile): Promise<StateTracker> {
111+
private async getTotalState(profile: Profile|ImmutableProfile): Promise<StateTracker> {
112112
const totalStateFilePath = profile.joinToProfilePath("_state", "installation_state.yml");
113113
let totalState: StateTracker = {
114114
currentState: []

src/r2mm/installing/profile_installers/GenericProfileInstaller.ts

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import ProfileInstallerProvider from '../../../providers/ror2/installing/ProfileInstallerProvider';
22
import ManifestV2 from '../../../model/ManifestV2';
3-
import Profile from '../../../model/Profile';
3+
import Profile, { ImmutableProfile } from '../../../model/Profile';
44
import FileTree from '../../../model/file/FileTree';
55
import R2Error from '../../../model/errors/R2Error';
66
import ModLoaderPackageMapping from '../../../model/installing/ModLoaderPackageMapping';
@@ -35,7 +35,7 @@ export default class GenericProfileInstaller extends ProfileInstallerProvider {
3535
this.legacyInstaller = new InstallRuleInstaller(this.rule);
3636
}
3737

38-
private async applyModModeForSubdir(mod: ManifestV2, tree: FileTree, profile: Profile, location: string, mode: number): Promise<R2Error | void> {
38+
private async applyModModeForSubdir(mod: ManifestV2, profile: ImmutableProfile, mode: number): Promise<R2Error | void> {
3939
// TODO: Call through the installer interface. For now we hardcode the only known case because expanding the
4040
// installer system is out of scope.
4141
//
@@ -82,19 +82,21 @@ export default class GenericProfileInstaller extends ProfileInstallerProvider {
8282
}
8383
}
8484

85-
private async applyModModeForState(mod: ManifestV2, tree: FileTree, profile: Profile, location: string, mode: number): Promise<R2Error | void> {
85+
private async applyModModeForState(mod: ManifestV2, profile: ImmutableProfile, mode: number): Promise<R2Error | void> {
86+
profile.getProfilePath()
8687
try {
87-
const modStateFilePath = path.join(location, "_state", `${mod.getName()}-state.yml`);
88+
const modStateFilePath = profile.joinToProfilePath("_state", `${mod.getName()}-state.yml`);
8889
if (await FsProvider.instance.exists(modStateFilePath)) {
8990
const fileContents = (await FsProvider.instance.readFile(modStateFilePath)).toString();
9091
const tracker: ModFileTracker = yaml.parse(fileContents);
9192
for (const [key, value] of tracker.files) {
9293
if (await ConflictManagementProvider.instance.isFileActive(mod, profile, value)) {
93-
if (await FsProvider.instance.exists(path.join(location, value))) {
94-
await FsProvider.instance.unlink(path.join(location, value));
94+
const filePath = profile.joinToProfilePath(value);
95+
if (await FsProvider.instance.exists(filePath)) {
96+
await FsProvider.instance.unlink(filePath);
9597
}
9698
if (mode === ModMode.ENABLED) {
97-
await FsProvider.instance.copyFile(key, path.join(location, value));
99+
await FsProvider.instance.copyFile(key, filePath);
98100
}
99101
}
100102
}
@@ -104,41 +106,23 @@ export default class GenericProfileInstaller extends ProfileInstallerProvider {
104106
}
105107
}
106108

107-
async applyModMode(mod: ManifestV2, tree: FileTree, profile: Profile, location: string, mode: number): Promise<R2Error | void> {
108-
const appliedState = await this.applyModModeForState(mod, tree, profile, location, mode);
109+
private async applyModMode(mod: ManifestV2, profile: ImmutableProfile, mode: number): Promise<R2Error | void> {
110+
const appliedState = await this.applyModModeForState(mod, profile, mode);
109111
if (appliedState instanceof R2Error) {
110112
return appliedState;
111113
}
112-
const appliedSub = await this.applyModModeForSubdir(mod, tree, profile, location, mode);
114+
const appliedSub = await this.applyModModeForSubdir(mod, profile, mode);
113115
if (appliedSub instanceof R2Error) {
114116
return appliedSub;
115117
}
116118
}
117119

118-
async disableMod(mod: ManifestV2, profile: Profile): Promise<R2Error | void> {
119-
return this.applyModMode(mod, new FileTree(), profile, profile.getProfilePath(), ModMode.DISABLED);
120+
async disableMod(mod: ManifestV2, profile: ImmutableProfile): Promise<R2Error | void> {
121+
return this.applyModMode(mod, profile, ModMode.DISABLED);
120122
}
121123

122-
async enableMod(mod: ManifestV2, profile: Profile): Promise<R2Error | void> {
123-
return this.applyModMode(mod, new FileTree(), profile, profile.getProfilePath(), ModMode.ENABLED);
124-
}
125-
126-
async getDescendantFiles(tree: FileTree | null, location: string): Promise<string[]> {
127-
const files: string[] = [];
128-
if (tree === null) {
129-
const newTree = await FileTree.buildFromLocation(location);
130-
if (newTree instanceof R2Error) {
131-
return files;
132-
}
133-
tree = newTree;
134-
}
135-
for (const directory of tree.getDirectories()) {
136-
files.push(...(await this.getDescendantFiles(directory, path.join(location, directory.getDirectoryName()))));
137-
}
138-
tree.getFiles().forEach((file: string) => {
139-
files.push(file);
140-
})
141-
return files;
124+
async enableMod(mod: ManifestV2, profile: ImmutableProfile): Promise<R2Error | void> {
125+
return this.applyModMode(mod, profile, ModMode.ENABLED);
142126
}
143127

144128
async installForManifestV2(args: InstallArgs): Promise<R2Error | null> {

src/store/modules/ProfileModule.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,15 +180,15 @@ export default {
180180
onProgress?: (mod: ManifestV2) => void,
181181
}
182182
) {
183-
const profile = getters.activeProfileOrThrow;
183+
const profile = getters.activeProfileOrThrow.asImmutableProfile();
184184
await dispatch('disableModsFromProfile', {...params, profile});
185185
},
186186

187187
async disableModsFromProfile(
188188
{dispatch},
189189
params: {
190190
mods: ManifestV2[],
191-
profile: Profile,
191+
profile: ImmutableProfile,
192192
onProgress?: (mod: ManifestV2) => void,
193193
}
194194
) {
@@ -211,7 +211,7 @@ export default {
211211
}
212212

213213
// Update mod list status to mods.yml.
214-
const updatedList = await ProfileModList.updateMods(mods, profile.asImmutableProfile(), (mod) => mod.disable());
214+
const updatedList = await ProfileModList.updateMods(mods, profile, (mod) => mod.disable());
215215
if (updatedList instanceof R2Error) {
216216
throw updatedList;
217217
} else {
@@ -235,15 +235,15 @@ export default {
235235
onProgress?: (mod: ManifestV2) => void,
236236
}
237237
) {
238-
const profile = getters.activeProfileOrThrow;
238+
const profile = getters.activeProfileOrThrow.asImmutableProfile();
239239
await dispatch('enableModsOnProfile', {...params, profile});
240240
},
241241

242242
async enableModsOnProfile(
243243
{dispatch},
244244
params: {
245245
mods: ManifestV2[],
246-
profile: Profile,
246+
profile: ImmutableProfile,
247247
onProgress?: (mod: ManifestV2) => void,
248248
}
249249
) {
@@ -266,7 +266,7 @@ export default {
266266
}
267267

268268
// Update mod list status to mods.yml.
269-
const updatedList = await ProfileModList.updateMods(mods, profile.asImmutableProfile(), (mod) => mod.enable());
269+
const updatedList = await ProfileModList.updateMods(mods, profile, (mod) => mod.enable());
270270
if (updatedList instanceof R2Error) {
271271
throw updatedList;
272272
} else {

test/jest/__tests__/impl/install_logic/ReturnOfModding.Tests.spec.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
installLogicBeforeEach
99
} from '../../../__utils__/InstallLogicUtils';
1010
import R2Error from '../../../../../src/model/errors/R2Error';
11-
import Profile from '../../../../../src/model/Profile';
11+
import Profile, { ImmutableProfile } from '../../../../../src/model/Profile';
1212
import ProfileInstallerProvider from '../../../../../src/providers/ror2/installing/ProfileInstallerProvider';
1313

1414

@@ -36,15 +36,16 @@ describe('ReturnOfModding Installer Tests', () => {
3636

3737
test('Disabling/enabling the mod loader does nothing', async () => {
3838
const pkg = createManifest("ReturnOfModding", "ReturnOfModding");
39+
const profile = new ImmutableProfile("TestProfile");
3940
const loaders = ["version.dll", "d3d12.dll"];
4041
await createFilesIntoProfile(loaders);
4142

42-
await ProfileInstallerProvider.instance.disableMod(pkg, Profile.getActiveProfile());
43+
await ProfileInstallerProvider.instance.disableMod(pkg, profile);
4344
await expectFilesToExistInProfile(loaders);
4445

4546
pkg.disable();
4647

47-
await ProfileInstallerProvider.instance.enableMod(pkg, Profile.getActiveProfile());
48+
await ProfileInstallerProvider.instance.enableMod(pkg, profile);
4849
await expectFilesToExistInProfile(loaders);
4950
});
5051

@@ -95,6 +96,7 @@ describe('ReturnOfModding Installer Tests', () => {
9596

9697
test('Disabling/enabling a mod renames files', async () => {
9798
const pkg = createManifest("HelperFunctions", "Klehrik");
99+
const profile = new ImmutableProfile("TestProfile");
98100
const name = pkg.getName();
99101
const files = [
100102
`ReturnOfModding/plugins/${name}/main.lua`,
@@ -104,12 +106,12 @@ describe('ReturnOfModding Installer Tests', () => {
104106
];
105107
await createFilesIntoProfile(files);
106108

107-
await ProfileInstallerProvider.instance.disableMod(pkg, Profile.getActiveProfile());
109+
await ProfileInstallerProvider.instance.disableMod(pkg, profile);
108110
await expectFilesToExistInProfile(files.map((fileName) => `${fileName}.old`));
109111

110112
pkg.disable();
111113

112-
await ProfileInstallerProvider.instance.enableMod(pkg, Profile.getActiveProfile());
114+
await ProfileInstallerProvider.instance.enableMod(pkg, profile);
113115
await expectFilesToExistInProfile(files);
114116
});
115117
});

0 commit comments

Comments
 (0)