1
1
import { EOL } from "os" ;
2
-
3
- interface IRubyFunction {
4
- functionName : string ;
5
- functionParameters ?: string ;
6
- }
2
+ import * as path from "path" ;
3
+ import { PluginNativeDirNames , PODFILE_NAME } from "../constants" ;
7
4
8
5
export class CocoaPodsService implements ICocoaPodsService {
6
+ private static PODFILE_POST_INSTALL_SECTION_NAME = "post_install" ;
7
+ private static INSTALLER_BLOCK_PARAMETER_NAME = "installer" ;
8
+
9
9
constructor ( private $fs : IFileSystem ) { }
10
10
11
11
public getPodfileHeader ( targetName : string ) : string {
@@ -16,20 +16,133 @@ export class CocoaPodsService implements ICocoaPodsService {
16
16
return `${ EOL } end` ;
17
17
}
18
18
19
- public mergePodfileHookContent ( hookName : string , pathToPodfile : string ) : void {
20
- if ( ! this . $fs . exists ( pathToPodfile ) ) {
21
- throw new Error ( `The Podfile ${ pathToPodfile } does not exist.` ) ;
19
+ public getProjectPodfilePath ( projectRoot : string ) : string {
20
+ return path . join ( projectRoot , PODFILE_NAME ) ;
21
+ }
22
+
23
+ public async applyPluginPodfileToProject ( pluginData : IPluginData , projectData : IProjectData , nativeProjectPath : string ) : Promise < void > {
24
+ const pluginPodFilePath = this . getPluginPodfilePath ( pluginData ) ;
25
+ if ( ! this . $fs . exists ( pluginPodFilePath ) ) {
26
+ return ;
27
+ }
28
+
29
+ const { pluginPodfileContent, replacedFunctions } = this . buildPodfileContent ( pluginPodFilePath , pluginData . name ) ;
30
+ const pathToProjectPodfile = this . getProjectPodfilePath ( nativeProjectPath ) ;
31
+ const projectPodfileContent = this . $fs . exists ( pathToProjectPodfile ) ? this . $fs . readText ( pathToProjectPodfile ) . trim ( ) : "" ;
32
+
33
+ if ( projectPodfileContent . indexOf ( pluginPodfileContent ) === - 1 ) {
34
+ // Remove old occurences of the plugin from the project's Podfile.
35
+ this . removePluginPodfileFromProject ( pluginData , projectData , nativeProjectPath ) ;
36
+ let finalPodfileContent = this . $fs . exists ( pathToProjectPodfile ) ? this . getPodfileContentWithoutTarget ( projectData , this . $fs . readText ( pathToProjectPodfile ) ) : "" ;
37
+
38
+ if ( pluginPodfileContent . indexOf ( CocoaPodsService . PODFILE_POST_INSTALL_SECTION_NAME ) !== - 1 ) {
39
+ finalPodfileContent = this . addPostInstallHook ( replacedFunctions , finalPodfileContent , pluginPodfileContent ) ;
40
+ }
41
+
42
+ finalPodfileContent = `${ pluginPodfileContent } ${ EOL } ${ finalPodfileContent } ` ;
43
+ this . saveProjectPodfile ( projectData , finalPodfileContent , nativeProjectPath ) ;
44
+ }
45
+ }
46
+
47
+ public removePluginPodfileFromProject ( pluginData : IPluginData , projectData : IProjectData , projectRoot : string ) : void {
48
+ const pluginPodfilePath = this . getPluginPodfilePath ( pluginData ) ;
49
+
50
+ if ( this . $fs . exists ( pluginPodfilePath ) && this . $fs . exists ( this . getProjectPodfilePath ( projectRoot ) ) ) {
51
+ let projectPodFileContent = this . $fs . readText ( this . getProjectPodfilePath ( projectRoot ) ) ;
52
+ // Remove the data between #Begin Podfile and #EndPodfile
53
+ const regExpToRemove = new RegExp ( `${ this . getPluginPodfileHeader ( pluginPodfilePath ) } [\\s\\S]*?${ this . getPluginPodfileEnd ( ) } ` , "mg" ) ;
54
+ projectPodFileContent = projectPodFileContent . replace ( regExpToRemove , "" ) ;
55
+ projectPodFileContent = this . removePostInstallHook ( pluginData , projectPodFileContent ) ;
56
+
57
+ const defaultPodfileBeginning = this . getPodfileHeader ( projectData . projectName ) ;
58
+ const defaultContentWithPostInstallHook = `${ defaultPodfileBeginning } ${ EOL } ${ this . getPostInstallHookHeader ( ) } end${ EOL } end` ;
59
+ const defaultContentWithoutPostInstallHook = `${ defaultPodfileBeginning } end` ;
60
+ const trimmedProjectPodFileContent = projectPodFileContent . trim ( ) ;
61
+ if ( ! trimmedProjectPodFileContent || trimmedProjectPodFileContent === defaultContentWithPostInstallHook || trimmedProjectPodFileContent === defaultContentWithoutPostInstallHook ) {
62
+ this . $fs . deleteFile ( this . getProjectPodfilePath ( projectRoot ) ) ;
63
+ } else {
64
+ this . $fs . writeFile ( this . getProjectPodfilePath ( projectRoot ) , projectPodFileContent ) ;
65
+ }
22
66
}
67
+ }
68
+
69
+ private getPluginPodfilePath ( pluginData : IPluginData ) : string {
70
+ const pluginPlatformsFolderPath = pluginData . pluginPlatformsFolderPath ( PluginNativeDirNames . iOS ) ;
71
+ const pluginPodFilePath = path . join ( pluginPlatformsFolderPath , PODFILE_NAME ) ;
72
+ return pluginPodFilePath ;
73
+ }
23
74
24
- const podfileContent = this . $fs . readText ( pathToPodfile ) ;
75
+ private addPostInstallHook ( replacedFunctions : IRubyFunction [ ] , finalPodfileContent : string , pluginPodfileContent : string ) : string {
76
+ const postInstallHookStart = this . getPostInstallHookHeader ( ) ;
77
+ let postInstallHookContent = "" ;
78
+ _ . each ( replacedFunctions , rubyFunction => {
79
+ let functionExecution = rubyFunction . functionName ;
80
+ if ( rubyFunction . functionParameters && rubyFunction . functionParameters . length ) {
81
+ functionExecution = `${ functionExecution } ${ CocoaPodsService . INSTALLER_BLOCK_PARAMETER_NAME } ` ;
82
+ }
83
+
84
+ postInstallHookContent += ` ${ functionExecution } ${ EOL } ` ;
85
+ } ) ;
86
+
87
+ if ( postInstallHookContent ) {
88
+ const index = finalPodfileContent . indexOf ( postInstallHookStart ) ;
89
+ if ( index !== - 1 ) {
90
+ finalPodfileContent = finalPodfileContent . replace ( postInstallHookStart , `${ postInstallHookStart } ${ postInstallHookContent } ` ) ;
91
+ } else {
92
+ const postInstallHook = `${ postInstallHookStart } ${ postInstallHookContent } end` ;
93
+ finalPodfileContent = `${ finalPodfileContent } ${ postInstallHook } ` ;
94
+ }
95
+ }
96
+
97
+ return finalPodfileContent ;
98
+ }
99
+
100
+ private getPodfileContentWithoutTarget ( projectData : IProjectData , projectPodfileContent : string ) : string {
101
+ const podFileHeader = this . getPodfileHeader ( projectData . projectName ) ;
102
+
103
+ if ( _ . startsWith ( projectPodfileContent , podFileHeader ) ) {
104
+ projectPodfileContent = projectPodfileContent . substr ( podFileHeader . length ) ;
105
+
106
+ const podFileFooter = this . getPodfileFooter ( ) ;
107
+ // Only remove the final end in case the file starts with the podFileHeader
108
+ if ( _ . endsWith ( projectPodfileContent , podFileFooter ) ) {
109
+ projectPodfileContent = projectPodfileContent . substr ( 0 , projectPodfileContent . length - podFileFooter . length ) ;
110
+ }
111
+ }
112
+
113
+ return projectPodfileContent . trim ( ) ;
114
+ }
115
+
116
+ private saveProjectPodfile ( projectData : IProjectData , projectPodfileContent : string , projectRoot : string ) : void {
117
+ projectPodfileContent = this . getPodfileContentWithoutTarget ( projectData , projectPodfileContent ) ;
118
+ const podFileHeader = this . getPodfileHeader ( projectData . projectName ) ;
119
+ const podFileFooter = this . getPodfileFooter ( ) ;
120
+ const contentToWrite = `${ podFileHeader } ${ projectPodfileContent } ${ podFileFooter } ` ;
121
+ const projectPodfilePath = this . getProjectPodfilePath ( projectRoot ) ;
122
+ this . $fs . writeFile ( projectPodfilePath , contentToWrite ) ;
123
+ }
124
+
125
+ private removePostInstallHook ( pluginData : IPluginData , projectPodFileContent : string ) : string {
126
+ const regExp = new RegExp ( `^.*?${ this . getHookBasicFuncNameForPlugin ( CocoaPodsService . PODFILE_POST_INSTALL_SECTION_NAME , pluginData . name ) } .*?$\\r?\\n` , "gm" ) ;
127
+ projectPodFileContent = projectPodFileContent . replace ( regExp , "" ) ;
128
+ return projectPodFileContent ;
129
+ }
130
+
131
+ private getHookBasicFuncNameForPlugin ( hookName : string , pluginName : string ) : string {
132
+ // nativescript-hook and nativescript_hook should have different names, so replace all _ with ___ first and then replace all special symbols with _
133
+ // This will lead to a clash in case plugins are called nativescript-hook and nativescript___hook
134
+ const replacedPluginName = pluginName . replace ( / _ / g, "___" ) . replace ( / [ ^ A - Z a - z 0 - 9 _ ] / g, "_" ) ;
135
+ return `${ hookName } ${ replacedPluginName } ` ;
136
+ }
137
+
138
+ private replaceHookContent ( hookName : string , podfileContent : string , pluginName : string ) : { replacedContent : string , newFunctions : IRubyFunction [ ] } {
25
139
const hookStart = `${ hookName } do` ;
26
140
27
141
const hookDefinitionRegExp = new RegExp ( `${ hookStart } *(\\|(\\w+)\\|)?` , "g" ) ;
28
- let newFunctionNameIndex = 1 ;
29
142
const newFunctions : IRubyFunction [ ] = [ ] ;
30
143
31
144
const replacedContent = podfileContent . replace ( hookDefinitionRegExp , ( substring : string , firstGroup : string , secondGroup : string , index : number ) : string => {
32
- const newFunctionName = `${ hookName } ${ newFunctionNameIndex ++ } ` ;
145
+ const newFunctionName = `${ this . getHookBasicFuncNameForPlugin ( hookName , pluginName ) } _ ${ newFunctions . length } ` ;
33
146
let newDefinition = `def ${ newFunctionName } ` ;
34
147
35
148
const rubyFunction : IRubyFunction = { functionName : newFunctionName } ;
@@ -43,26 +156,31 @@ export class CocoaPodsService implements ICocoaPodsService {
43
156
return newDefinition ;
44
157
} ) ;
45
158
46
- if ( newFunctions . length > 1 ) {
47
- // Execute all methods in the hook and pass the parameter to them.
48
- const blokParameterName = "installer" ;
49
- let mergedHookContent = `${ hookStart } |${ blokParameterName } |${ EOL } ` ;
159
+ return { replacedContent, newFunctions } ;
160
+ }
50
161
51
- _ . each ( newFunctions , ( rubyFunction : IRubyFunction ) => {
52
- let functionExecution = rubyFunction . functionName ;
53
- if ( rubyFunction . functionParameters && rubyFunction . functionParameters . length ) {
54
- functionExecution = `${ functionExecution } ${ blokParameterName } ` ;
55
- }
162
+ private getPluginPodfileHeader ( pluginPodFilePath : string ) : string {
163
+ return `# Begin Podfile - ${ pluginPodFilePath } ` ;
164
+ }
56
165
57
- mergedHookContent = `${ mergedHookContent } ${ functionExecution } ${ EOL } ` ;
58
- } ) ;
166
+ private getPluginPodfileEnd ( ) : string {
167
+ return `# End Podfile${ EOL } ` ;
168
+ }
59
169
60
- mergedHookContent = `${ mergedHookContent } end` ;
170
+ private getPostInstallHookHeader ( ) {
171
+ return `${ CocoaPodsService . PODFILE_POST_INSTALL_SECTION_NAME } do |${ CocoaPodsService . INSTALLER_BLOCK_PARAMETER_NAME } |${ EOL } ` ;
172
+ }
61
173
62
- const newPodfileContent = `${ replacedContent } ${ EOL } ${ mergedHookContent } ` ;
63
- this . $fs . writeFile ( pathToPodfile , newPodfileContent ) ;
64
- }
174
+ private buildPodfileContent ( pluginPodFilePath : string , pluginName : string ) : { pluginPodfileContent : string , replacedFunctions : IRubyFunction [ ] } {
175
+ const pluginPodfileContent = this . $fs . readText ( pluginPodFilePath ) ;
176
+ const { replacedContent, newFunctions : replacedFunctions } = this . replaceHookContent ( CocoaPodsService . PODFILE_POST_INSTALL_SECTION_NAME , pluginPodfileContent , pluginName ) ;
177
+
178
+ return {
179
+ pluginPodfileContent : `${ this . getPluginPodfileHeader ( pluginPodFilePath ) } ${ EOL } ${ replacedContent } ${ EOL } ${ this . getPluginPodfileEnd ( ) } ` ,
180
+ replacedFunctions
181
+ } ;
65
182
}
183
+
66
184
}
67
185
68
186
$injector . register ( "cocoapodsService" , CocoaPodsService ) ;
0 commit comments