Skip to content

feat: make app_resources's path configurable #3329

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

Closed
wants to merge 6 commits into from

Conversation

petekanev
Copy link
Contributor

@petekanev petekanev commented Jan 22, 2018

Refactor the project-data service to read a config.json for the 'appResources' property entry, which points relatively to the App_Resources directory.

  • All references to app/App_Resources now retrieve the path from the said service.

  • To keep the service backward compatible, if no config.json is present, or the appResources entry isn't available, location defaults to projectDir/app/App_Resources.

  • Change the app-files-updater class to not collect the App_Resources directory when enumerating through the user's source files. Instead a separate method will enumerate the App_Resources directory and its files, and will copy it in platforms/**/app. I find that behavior to be more predictable, otherwise enumerating just the myProject/app directory, could skip enumerating the App_Resources if they are located someplace else, as declared in the nsconfig.json file.

@KristianDD
Copy link
Contributor

run ci

1 similar comment
@dtopuzov
Copy link
Contributor

run ci

}

protected resolveAppSourceFiles(): string[] {
// Copy all files from app dir, but make sure to exclude tns_modules
// Copy all files from app dir, but make sure to exclude tns_modules and App_Resources
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this change applied? Can you describe it in the commit message

this.projectDir = this.projectDir || projectDir;
}
public getAppResourcesDirectoryPath(projectDir?: string): string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this stub uses the same implementation from the real class, by duplicating the code. Is there a particular reason for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found it easier to test this way, since I would always get the default path to the App_Resources. Ideally I could always resolve the path to the default app/App_Resources for the purposes of testing.

@@ -65,12 +65,13 @@ function createTestInjector(projectPath: string, projectName: string): IInjector
testInjector.register("iOSEntitlementsService", IOSEntitlementsService);
testInjector.register("logger", LoggerLib.Logger);
testInjector.register("options", OptionsLib.Options);
testInjector.register("projectData", {
const projectData = Object.assign({}, ProjectDataStub, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe you can just mock the required methods, but this is not a merge stopper

@@ -46,7 +47,7 @@ describe("IOSEntitlements Service Tests", () => {
injector = createTestInjector();

platformsData = injector.resolve("platformsData");
projectData = <IProjectData>platformsData.getPlatformData();
projectData = injector.resolve("projectData");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use:

projectData = $injector.resolve<IProjectData>("projectData");

if (configNS && configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY]) {
const appResourcesDirPath = configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY];

absoluteAppResourcesDirPath = path.resolve(projectDir, appResourcesDirPath);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it worth checking if this path exists?

@@ -87,6 +88,27 @@ export class ProjectData implements IProjectData {
this.$errors.fail("No project found at or above '%s' and neither was a --path specified.", projectDir || this.$options.path || currentDir);
}

public getAppResourcesDirectoryPath(projectDir?: string): string {
if (!projectDir) {
projectDir = this.projectDir;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if initializeProjectData has not been called, the this.projectDir will also be undefined and the path.join below will fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, I am unsure how to tackle this. The need for the additional projectDir parameter arose when using the getter during project creation. What would you recommend I check here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just return null here. The caller should decide what to do.

lib/constants.ts Outdated
@@ -28,6 +28,8 @@ export const BUILD_DIR = "build";
export const OUTPUTS_DIR = "outputs";
export const APK_DIR = "apk";
export const RESOURCES_DIR = "res";
export const CONFIG_NS_FILE_NAME = "nsconfig.json";
export const CONFIG_NS_APP_RESOURCES_ENTRY = "app_resources";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer naming json properties in camelCase (appResources in this case), but I do not have a strong opinion here. @KristianDD , @Mitko-Kerezov what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll follow the convention seemingly established in package.json and tsconfig and go with camelCase.

@@ -36,6 +36,7 @@ export class PreparePlatformJSService extends PreparePlatformService implements
public async preparePlatform(config: IPreparePlatformJSInfo): Promise<void> {
if (!config.changesInfo || config.changesInfo.appFilesChanged || config.changesInfo.changesRequirePrepare) {
await this.copyAppFiles(config);
this.copyAppResourcesFiles(config);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is related to https://github.com/NativeScript/nativescript-cli/pull/3329/files#diff-d7315453ac31262b45d0c2530d69cd94R47 change. Can you describe a little bit more what is the idea

@rosen-vladimirov
Copy link
Contributor

@Pip3r4o I've tried the following commands with the current branch and some warnings are shown from gradle:

$ tns create myApp
$ cd myApp
$ tns build android
$ mv app/App_Resources my_app_resources
$ tns build android -
Warning is printed: 
No manifest found in `<path to project>\app\App_Resources\Android\AndroidManifest.xml`, but build continues.
$ vi nsconfig.json // set the following content { "app_resources": "my_app_resources" }
$ tns build android
Preparing project...
Project successfully prepared (android)
Building project...
Gradle build...
         + couldn't load user-defined configuration from D:\Work\nativescript-cli\scratch\app74\app\App_Resources\Android\app.gradle. File doesn't exist.
         + adding nativescript runtime package dependency: nativescript-optimized
         + adding aar plugin dependency: D:\Work\nativescript-cli\scratch\app74\node_modules\tns-core-modules-widgets\platforms\android\widgets-release.aar
false
Running full build
Project successfully built.

@petekanev
Copy link
Contributor Author

@rosen-vladimirov the gradle build script from the android-runtime release and master branches currently reads the app.gradle from a hardcoded path to the app_resources. There's an additional PR that uses a method similar to getAppResourcesDirectoryPath in order to locate the App_Resources dir.

Copy link
Contributor

@KristianDD KristianDD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly after testing this PR the provided path inside nsconfig.json should end with "App_Resources" otherwise the CLI will fail to build the project.

We should either
1 Fix it - find where APP_RESOURCES_FOLDER_NAME is used and make sure it is used only for the destination of the resources inside platforms folder.

2 Validate the path provided, but this will make the user experience worse.

@petekanev
Copy link
Contributor Author

@rosen-vladimirov @KristianDD I made some changes after taking your comments into consideration. Please review.

@@ -103,10 +107,17 @@ export class ProjectData implements IProjectData {
const appResourcesDirPath = configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY];

absoluteAppResourcesDirPath = path.resolve(projectDir, appResourcesDirPath);

if (this.$fs.exists(absoluteAppResourcesDirPath)) {
Copy link
Contributor

@KristianDD KristianDD Feb 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check what happens if we go through here

private async ensureAppResourcesExist(projectDir: string): Promise<void> {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KristianDD
Creating an ng/ts project, which would suggest that 2 templates will be downloaded - one before ensureAppResourcesExist is called, the other one - afterwards, doesn't make the process crash. I am not sure if the case would be the same if the template is shipped with nsconfig.json which points to App_Resources.

What do you think? Should I perhaps return the path, even if the directory doesn't exist, as that's where the App_Resources from the template should be extracted?

// exclude the app_resources directory from being enumerated
// for copying if it is present in the application sources dir
const appResourcesPath = projectData.appResourcesDirectoryPath;
const appResourcesDirInSources = path.join(this.appSourceDirectoryPath, path.basename(appResourcesPath));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if it works with appResourcesPath directly.

petekanev and others added 5 commits February 22, 2018 17:59
Refactor the project-data service to read a config.json for the
'app_resources' property entry, which points relatively to the
App_Resources directory.

All references to app/App_Resources now retrieve the path from
said service.

To keep the service backwards compatible, if no config.json is
present, or the app_resources entry isn't available, location
defaults to projectDir/app/App_Resources.
@petekanev petekanev force-pushed the pete/nsconfig-json branch 2 times, most recently from dc0cdaf to 990ec08 Compare February 22, 2018 16:18
the name of the app_resources directory basename is
@petekanev
Copy link
Contributor Author

Closing this PR in favor of #3356 which includes the changes presented here.

@petekanev petekanev closed this Feb 26, 2018
@petekanev petekanev deleted the pete/nsconfig-json branch March 8, 2018 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants