diff --git a/src/main/groovy/com/github/j2objccontrib/j2objcgradle/J2objcConfig.groovy b/src/main/groovy/com/github/j2objccontrib/j2objcgradle/J2objcConfig.groovy
index 2f381748..31687549 100644
--- a/src/main/groovy/com/github/j2objccontrib/j2objcgradle/J2objcConfig.groovy
+++ b/src/main/groovy/com/github/j2objccontrib/j2objcgradle/J2objcConfig.groovy
@@ -622,7 +622,8 @@ class J2objcConfig {
*
* See https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html#//apple_ref/doc/uid/10000163i-CH1-SW2
*/
- String minIosVersion = '6.0'
+ // Matches the oldest version supported in Xcode 7
+ String minVersionIos = '6.0'
/**
* The minimum OS X version to build against. You cannot use APIs that are not supported
@@ -630,7 +631,8 @@ class J2objcConfig {
*
* See https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html#//apple_ref/doc/uid/10000163i-CH1-SW2
*/
- String minOsxVersion = '10.4'
+ // Matches the oldest version supported in Xcode 7
+ String minVersionOsx = '10.4'
/**
* The minimum Watch OS version to build against. You cannot use APIs that are not supported
@@ -638,7 +640,8 @@ class J2objcConfig {
*
* See https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html#//apple_ref/doc/uid/10000163i-CH1-SW2
*/
- String minWatchosVersion = '1.0'
+ // Matches the oldest version supported in Xcode 7
+ String minVersionWatchos = '1.0'
// XCODE
/**
@@ -649,28 +652,54 @@ class J2objcConfig {
*
*/
String xcodeProjectDir = null
+
/**
- * Xcode app targets that should be linked to the generated library.
+ * iOS app and test Xcode targets to link to the generated libraries.
*
* This will automatically add linkage for any target in the specified list
- * to the generated shared library. This should include any Test and Watch
- * targets if needed.
+ * to the generated shared libraries. This should include test targets also.
+ */
+ List xcodeTargetsIos = new ArrayList<>()
+ /**
+ * iOS app and test Xcode targets to link to the generated libraries.
*
- * If empty (default), it will link all targets defined within the Xcode project.
+ * @param xcodeTargetsIos targets to link to the generated libraries.
*/
- List xcodeTargets = new ArrayList<>()
+ void xcodeTargetsIos(String... xcodeTargetsIos) {
+ appendArgs(this.xcodeTargetsIos, 'xcodeTargetsIos', xcodeTargetsIos)
+ }
+
/**
- * Add targets within Xcode to link to the generated shared library.
+ * OS X app and test Xcode targets that should be linked to the generated libraries.
*
- * If this is never called, it will default to linking all targets
- * to the generated shared library.
+ * This will automatically add linkage for any target in the specified list
+ * to the generated shared libraries. This should include test targets also.
+ */
+ List xcodeTargetsOsx = new ArrayList<>()
+ /**
+ * OS X app and test Xcode targets to link to the generated libraries.
*
- * @param xcodeTargets links targets to generated library.
+ * @param xcodeTargetsOsx targets to link to the generated libraries.
*/
- void xcodeTargets(String... xcodeTargets) {
- appendArgs(this.xcodeTargets, 'xcodeTargets', xcodeTargets)
+ void xcodeTargetsOsx(String... xcodeTargetsOsx) {
+ appendArgs(this.xcodeTargetsOsx, 'xcodeTargetsOsx', xcodeTargetsOsx)
}
+ /**
+ * watchOS app and test Xcode targets that should be linked to the generated libraries.
+ *
+ * This will automatically add linkage for any target in the specified list
+ * to the generated shared libraries. This should include test targets also.
+ */
+ List xcodeTargetsWatchos = new ArrayList<>()
+ /**
+ * watchOS app and test Xcode targets to link to the generated libraries.
+ *
+ * @param xcodeTargetsWatchos targets to link to the generated libraries.
+ */
+ void xcodeTargetsWatchos(String... xcodeTargetsWatchos) {
+ appendArgs(this.xcodeTargetsWatchos, 'xcodeTargetsWatchos', xcodeTargetsWatchos)
+ }
protected boolean finalConfigured = false
diff --git a/src/main/groovy/com/github/j2objccontrib/j2objcgradle/NativeCompilation.groovy b/src/main/groovy/com/github/j2objccontrib/j2objcgradle/NativeCompilation.groovy
index 2350b96c..3196719c 100644
--- a/src/main/groovy/com/github/j2objccontrib/j2objcgradle/NativeCompilation.groovy
+++ b/src/main/groovy/com/github/j2objccontrib/j2objcgradle/NativeCompilation.groovy
@@ -87,12 +87,12 @@ class NativeCompilation {
switch (targetSpec) {
case TargetSpec.TARGET_IOS_DEVICE:
clangArgs += iphoneClangArgs
- clangArgs += ["-miphoneos-version-min=${config.minIosVersion}"]
+ clangArgs += ["-miphoneos-version-min=${config.minVersionIos}"]
linkerArgs += ["-L$j2objcPath/lib"]
break
case TargetSpec.TARGET_IOS_SIMULATOR:
clangArgs += simulatorClangArgs
- clangArgs += ["-mios-simulator-version-min=${config.minIosVersion}"]
+ clangArgs += ["-mios-simulator-version-min=${config.minVersionIos}"]
linkerArgs += ["-L$j2objcPath/lib"]
break
case TargetSpec.TARGET_OSX:
diff --git a/src/main/groovy/com/github/j2objccontrib/j2objcgradle/tasks/PodspecTask.groovy b/src/main/groovy/com/github/j2objccontrib/j2objcgradle/tasks/PodspecTask.groovy
index 5ced6566..1452d2eb 100644
--- a/src/main/groovy/com/github/j2objccontrib/j2objcgradle/tasks/PodspecTask.groovy
+++ b/src/main/groovy/com/github/j2objccontrib/j2objcgradle/tasks/PodspecTask.groovy
@@ -68,11 +68,11 @@ class PodspecTask extends DefaultTask {
String getPodNameRelease() { "j2objc-${project.name}-release" }
@Input
- String getMinIosVersion() { return J2objcConfig.from(project).getMinIosVersion() }
+ String getMinVersionIos() { return J2objcConfig.from(project).getMinVersionIos() }
@Input
- String getMinOsxVersion() { return J2objcConfig.from(project).getMinOsxVersion() }
+ String getMinVersionOsx() { return J2objcConfig.from(project).getMinVersionOsx() }
@Input
- String getMinWatchosVersion() { return J2objcConfig.from(project).getMinWatchosVersion() }
+ String getMinVersionWatchos() { return J2objcConfig.from(project).getMinVersionWatchos() }
// CocoaPods podspec files that are referenced by the Podfile
@@ -97,19 +97,19 @@ class PodspecTask extends DefaultTask {
String libDirOsxDebug = relativizeToBuildDir(new File(getDestLibDirFile(), 'x86_64Debug'), project)
String libDirOsxRelease = relativizeToBuildDir(new File(getDestLibDirFile(), 'x86_64Release'), project)
- validateNumericVersion(getMinIosVersion(), 'minIosVersion')
- validateNumericVersion(getMinOsxVersion(), 'minOsxVersion')
- validateNumericVersion(getMinWatchosVersion(), 'minWatchosVersion')
+ validateNumericVersion(getMinVersionIos(), 'minVersionIos')
+ validateNumericVersion(getMinVersionOsx(), 'minVersionOsx')
+ validateNumericVersion(getMinVersionWatchos(), 'minVersionWatchos')
String podspecContentsDebug =
genPodspec(getPodNameDebug(), headerIncludePath, resourceIncludePath,
libDirIosDebug, libDirOsxDebug, libDirIosDebug,
- getMinIosVersion(), getMinOsxVersion(), getMinWatchosVersion(),
+ getMinVersionIos(), getMinVersionOsx(), getMinVersionWatchos(),
getLibName(), getJ2objcHome())
String podspecContentsRelease =
genPodspec(getPodNameRelease(), headerIncludePath, resourceIncludePath,
libDirIosRelease, libDirOsxRelease, libDirIosRelease,
- getMinIosVersion(), getMinOsxVersion(), getMinWatchosVersion(),
+ getMinVersionIos(), getMinVersionOsx(), getMinVersionWatchos(),
getLibName(), getJ2objcHome())
logger.debug("Writing debug podspec... ${getPodspecDebug()}")
diff --git a/src/main/groovy/com/github/j2objccontrib/j2objcgradle/tasks/XcodeTask.groovy b/src/main/groovy/com/github/j2objccontrib/j2objcgradle/tasks/XcodeTask.groovy
index 2a3f77c4..922719c1 100644
--- a/src/main/groovy/com/github/j2objccontrib/j2objcgradle/tasks/XcodeTask.groovy
+++ b/src/main/groovy/com/github/j2objccontrib/j2objcgradle/tasks/XcodeTask.groovy
@@ -44,10 +44,28 @@ import java.util.regex.Matcher
@CompileStatic
class XcodeTask extends DefaultTask {
+
+ public static final String targetStartRegex = /^\s*target\s+'([^']*)'\s+do\s*$/
+ public static final String targetNamedRegex = /^\s*target\s+'TARGET'\s+do\s*$/
+ public static final String podMethodStartRegex = /^\s*((def\s*j2objc_)|(# J2ObjC Gradle Plugin)).*/
+ public static final String endRegex = /^\s*end\s*/
+
@Input @Optional
String getXcodeProjectDir() { return J2objcConfig.from(project).xcodeProjectDir }
- @Input @Optional
- List getXcodeTargets() { return J2objcConfig.from(project).xcodeTargets }
+
+ @Input
+ List getXcodeTargetsIos() { return J2objcConfig.from(project).xcodeTargetsIos }
+ @Input
+ List getXcodeTargetsOsx() { return J2objcConfig.from(project).xcodeTargetsOsx }
+ @Input
+ List getXcodeTargetsWatchos() { return J2objcConfig.from(project).xcodeTargetsWatchos }
+
+ @Input
+ String getMinVersionIos() { return J2objcConfig.from(project).minVersionIos }
+ @Input
+ String getMinVersionOsx() { return J2objcConfig.from(project).minVersionOsx }
+ @Input
+ String getMinVersionWatchos() { return J2objcConfig.from(project).minVersionWatchos }
@OutputFile
File getPodfileFile() {
@@ -56,21 +74,41 @@ class XcodeTask extends DefaultTask {
}
static class PodspecDetails {
+ String projectName
+ File podspecDebug
+ File podspecRelease
+
PodspecDetails(String projectNameIn, File podspecDebugIn, File podspecReleaseIn) {
projectName = projectNameIn
podspecDebug = podspecDebugIn
podspecRelease = podspecReleaseIn
}
- String projectName
- File podspecDebug
- File podspecRelease
-
String getPodMethodName() {
return "j2objc_$projectName"
}
}
+ static class XcodeTargetDetails {
+ List xcodeTargetsIos
+ List xcodeTargetsOsx
+ List xcodeTargetsWatchos
+ String minVersionIos
+ String minVersionOsx
+ String minVersionWatchos
+
+ XcodeTargetDetails(
+ List xcodeTargetsIosIn, List xcodeTargetsOsxIn, List xcodeTargetsWatchosIn,
+ String minVersionIosIn, String minVersionOsxIn, String minVersionWatchosIn) {
+ xcodeTargetsIos = xcodeTargetsIosIn
+ xcodeTargetsOsx = xcodeTargetsOsxIn
+ xcodeTargetsWatchos = xcodeTargetsWatchosIn
+ minVersionIos = minVersionIosIn
+ minVersionOsx = minVersionOsxIn
+ minVersionWatchos = minVersionWatchosIn
+ }
+ }
+
@TaskAction
void xcodeConfig() {
@@ -106,7 +144,12 @@ class XcodeTask extends DefaultTask {
// Write Podfile based on all the podspecs from dependent projects
List podspecDetailsList =
getPodspecsFromProject(getProject(), new HashSet())
- writeUpdatedPodfileIfNeeded(podspecDetailsList, getXcodeTargets(), podfile, logger)
+
+ XcodeTargetDetails xcodeTargetDetails = new XcodeTargetDetails(
+ getXcodeTargetsIos(), getXcodeTargetsOsx(), getXcodeTargetsWatchos(),
+ getMinVersionIos(), getMinVersionOsx(), getMinVersionWatchos())
+
+ writeUpdatedPodfileIfNeeded(podspecDetailsList, xcodeTargetDetails, podfile, logger)
// install the pod
ByteArrayOutputStream stdout = new ByteArrayOutputStream()
@@ -193,19 +236,13 @@ class XcodeTask extends DefaultTask {
}
/**
- * Extracts all target names within the Podfile.
- *
- * For an app target named 'IOS-APP', likely target names are:
- * IOS-APP
- * IOS-APPTests
- * IOS-APP WatchKit App
- * IOS-APP WatchKit Extension
+ * Extracts xcode targets in Podfile.
*/
@VisibleForTesting
static List extractXcodeTargets(List podfileLines) {
List xcodeTargets = new ArrayList<>()
for (line in podfileLines) {
- Matcher matcher = (line =~ /^target '([^']*)' do$/)
+ Matcher matcher = (line =~ targetStartRegex)
if (matcher.find()) {
xcodeTargets.add(matcher.group(1))
}
@@ -213,22 +250,112 @@ class XcodeTask extends DefaultTask {
return xcodeTargets
}
+ /**
+ * Strips certain lines from podfile.
+ *
+ * Stripping is applied from startRegex, stopping immediately before endRegex,
+ * the line is removed if and only if it matches stripRegex.
+ * Throws if startRegex is found but not endRegex.
+ */
+ @VisibleForTesting
+ static List regexStripLines(List podfileLines, boolean multipleMatches,
+ String startRegex, String endRegex, String stripRegex) {
+ List result = new ArrayList<>()
+ boolean active = false
+ boolean completedFirstMatch = false
+
+ for (line in podfileLines) {
+ if (completedFirstMatch && !multipleMatches) {
+ // Ignoring 2nd and later matches
+ result.add(line)
+ } else {
+ if ((line =~ startRegex).find()) {
+ active = true
+ }
+ if ((line =~ endRegex).find()) {
+ active = false
+ completedFirstMatch = true
+ }
+ // strip line only within 'active' range
+ if (!active || !(line =~ stripRegex).find()) {
+ result.add(line)
+ }
+ }
+ }
+ if (active) {
+ throw new InvalidUserDataException(
+ "Failed to find endRegex: ${Utils.escapeSlashyString(endRegex)}\n" +
+ podfileLines.join('\n'))
+ }
+ return result
+ }
+
+ /**
+ * Insert new lines in to podfile between startRegex to endRegex.
+ *
+ * Throws error for no match or multiple matches.
+ */
+ @VisibleForTesting
+ static List regexInsertLines(List podfileLines, boolean insertAfterStart,
+ String startRegex, String endRegex, List insertLines) {
+ List result = new ArrayList<>()
+ boolean active = false
+ boolean done = false
+
+ for (line in podfileLines) {
+ if (done) {
+ result.add(line)
+ } else {
+ boolean startFoundThisLoop = false
+ (line =~ startRegex).find() {
+ active = true
+ startFoundThisLoop = true
+ assert !done
+ }
+ (line =~ endRegex).find() {
+ if (active) {
+ if (!insertAfterStart) {
+ result.addAll(insertLines)
+ }
+ active = false
+ done = true
+ }
+ }
+ result.add(line)
+
+ if (startFoundThisLoop && insertAfterStart) {
+ result.addAll(insertLines)
+ }
+ }
+ }
+
+ if (active) {
+ throw new InvalidUserDataException(
+ "Failed to find endRegex: ${Utils.escapeSlashyString(endRegex)}\n" +
+ podfileLines.join('\n'))
+ }
+ if (!done) {
+ throw new InvalidUserDataException(
+ "Failed to find startRegex: ${Utils.escapeSlashyString(startRegex)}\n" +
+ podfileLines.join('\n'))
+ }
+ return result
+ }
+
/**
* Modify in place the existing podfile.
*/
@VisibleForTesting
static void writeUpdatedPodfileIfNeeded(
List podspecDetailsList,
- List xcodeTargets, File podfile, Logger logger) {
+ XcodeTargetDetails xcodeTargetDetails,
+ File podfile, Logger logger) {
List oldPodfileLines = podfile.readLines()
List newPodfileLines = new ArrayList(oldPodfileLines)
- podspecDetailsList.each { PodspecDetails podspecDetails ->
- newPodfileLines = updatePodfile(
- newPodfileLines, podspecDetails,
- xcodeTargets, podfile, logger)
- }
+ newPodfileLines = updatePodfile(
+ newPodfileLines, podspecDetailsList, xcodeTargetDetails, podfile, logger)
// Write file only if it's changed
if (!oldPodfileLines.equals(newPodfileLines)) {
@@ -238,57 +365,78 @@ class XcodeTask extends DefaultTask {
@VisibleForTesting
static List updatePodfile(
- List oldPodfileLines, PodspecDetails podspecDetails,
- List xcodeTargets, File podfile, Logger logger) {
+ List podfileLines,
+ List podspecDetailsList,
+ XcodeTargetDetails xcodeTargetDetails,
+ File podfile, Logger logger) {
+
+ List podfileTargets = extractXcodeTargets(podfileLines)
+ verifyTargets(xcodeTargetDetails.xcodeTargetsIos, podfileTargets, 'xcodeTargetsIos')
+ verifyTargets(xcodeTargetDetails.xcodeTargetsOsx, podfileTargets, 'xcodeTargetsOsx')
+ verifyTargets(xcodeTargetDetails.xcodeTargetsWatchos, podfileTargets, 'xcodeTargetsWatchos')
+
+ if (xcodeTargetDetails.xcodeTargetsIos.isEmpty() &&
+ xcodeTargetDetails.xcodeTargetsOsx.isEmpty() &&
+ xcodeTargetDetails.xcodeTargetsWatchos.isEmpty()) {
+ // Need to warn about configuring
+ throw new InvalidUserDataException(
+ "You must configure the xcode targets for the J2ObjC Gradle Plugin.\n" +
+ "It must be a subset of the valid targets: '${podfileTargets.join("', '")}'\n" +
+ "\n" +
+ "j2objcConfig {\n" +
+ " xcodeTargetsIos 'IOS-APP', 'IOS-APPTests' // example\n" +
+ "}\n" +
+ "\n" +
+ "Can be optionally configured for xcodeTargetsOsx and xcodeTargetsWatchos\n")
+ }
- List podfileTargets = extractXcodeTargets(oldPodfileLines)
- List newPodfileLines = new ArrayList(oldPodfileLines)
+ // update pod methods
+ List newPodfileLines = updatePodMethods(podfileLines, podspecDetailsList, podfile)
- // No targets set, then default to all
- if (xcodeTargets.size() == 0) {
- xcodeTargets = podfileTargets
- if (logger) {
- logger.debug("xcodeTargets default is all targets: '${podfileTargets.join(', ')}'")
- }
- } else {
- for (xcodeTarget in xcodeTargets) {
- if (! (xcodeTarget in podfileTargets)) {
- // Error checking for zero or non-existent xcodeTargets
- throw new InvalidUserDataException(
- "Current xcodeTargets: xcodeTargets\n" +
- "Valid xcodeTargets must be subset (likely all) of: $podfileTargets\n" +
- "\n" +
- "j2objcConfig {\n" +
- " xcodeTargets '${podfileTargets.join(', ')}'\n" +
- "}\n")
- }
+ // Iterate over all podfileTargets as some may need to be cleared
+ newPodfileLines = updatePodfileTargets(
+ newPodfileLines, podspecDetailsList, xcodeTargetDetails)
+
+ return newPodfileLines
+ }
+
+ private static verifyTargets(List xcodeTargets, List podfileTargets, xcodeTargetsName) {
+ xcodeTargets.each { String xcodeTarget ->
+ if (! podfileTargets.contains(xcodeTarget)) {
+ throw new InvalidUserDataException(
+ "Invalid j2objcConfig { $xcodeTargetsName '$xcodeTarget' }\n" +
+ "Must be one of the valid targets: '${podfileTargets.join("', '")}'")
}
}
+ }
+
+ @VisibleForTesting
+ static List updatePodMethods(
+ List podfileLines, List podspecDetailsList, File podfile) {
- // Install shared shared pod for multiple targets
- // http://natashatherobot.com/cocoapods-installing-same-pod-multiple-targets/
- newPodfileLines = updatePodfileMethod(
- newPodfileLines, podspecDetails, podfile)
+ // strip all old methods
+ // Note: use of preserveEndLine=true so that the targetStartRegex isn't removed
+ List newPodfileLines =
+ regexStripLines(podfileLines, false, podMethodStartRegex, targetStartRegex, /.*/)
- // Iterate over all podfileTargets as some may need to be cleared
- for (podfileTarget in podfileTargets) {
- boolean addPodMethod = podfileTarget in xcodeTargets
- newPodfileLines = updatePodfileTarget(
- newPodfileLines, podfileTarget,
- podspecDetails.getPodMethodName(), addPodMethod)
+ // create new methods
+ List insertLines = new ArrayList<>()
+ insertLines.add('# J2ObjC Gradle Plugin - DO NOT MODIFY from here to the first target')
+ podspecDetailsList.each { PodspecDetails podspecDetails ->
+ insertLines.addAll(podMethodLines(podspecDetails, podfile))
+ insertLines.add('')
}
+
+ // insert new methods immediately before first target
+ newPodfileLines = regexInsertLines(newPodfileLines, false, /.*/, targetStartRegex, insertLines)
+
return newPodfileLines
}
- private static List updatePodfileMethod(
- List oldPodfileLines, PodspecDetails podspecDetails, File podfile) {
-
- List newPodfileLines = new ArrayList<>()
- boolean podMethodFound = false
- boolean podMethodProcessed = false
+ @VisibleForTesting
+ static List podMethodLines(
+ PodspecDetails podspecDetails, File podfile) {
- // Extract podspec details. Example given for debug podspec
- //
// Inputs:
// podNameMethod: j2objc_PROJECT
// podfile: /SRC/ios/Podfile
@@ -308,51 +456,12 @@ class XcodeTask extends DefaultTask {
// Search for pod within the xcodeTarget, until "end" is found for that target
// Either update pod line in place or add line if pod doesn't exist
- List newPodMethodLines = new ArrayList<>()
- newPodMethodLines.add("def ${podspecDetails.getPodMethodName()}".toString())
- newPodMethodLines.add(" pod '$podspecDebugName', :configuration => ['Debug'], :path => '$pathDebug'".toString())
- newPodMethodLines.add(" pod '$podspecReleaseName', :configuration => ['Release'], :path => '$pathRelease'".toString())
- newPodMethodLines.add("end")
-
- oldPodfileLines.each { String line ->
- // Copies each line to newPodfileLines, unless skipped
- boolean skipWritingLine = false
-
- if (!podMethodProcessed) {
- // Look for pod method start: def j2objc_shared
- if (!podMethodFound) {
- if (line.contains(newPodMethodLines.get(0))) {
- podMethodFound = true
- }
- }
-
- if (podMethodFound) {
- // Generate new pod method contents each time
- skipWritingLine = true
-
- if (line.trim() == 'end') {
- // End of old pod method
- newPodfileLines.addAll(newPodMethodLines)
- // Generate new pod method each time
- podMethodProcessed = true
- }
- }
-
- if (line.trim().startsWith("target '")) {
- // pod method wasn't found, so needs to be written anyway
- newPodfileLines.addAll(newPodMethodLines)
- // Blank line
- newPodfileLines.add('')
- podMethodProcessed = true
- }
- }
-
- if (!skipWritingLine) {
- newPodfileLines.add(line)
- }
- }
-
- return newPodfileLines
+ List podMethodLines = new ArrayList<>()
+ podMethodLines.add("def ${podspecDetails.getPodMethodName()}".toString())
+ podMethodLines.add(" pod '$podspecDebugName', :configuration => ['Debug'], :path => '$pathDebug'".toString())
+ podMethodLines.add(" pod '$podspecReleaseName', :configuration => ['Release'], :path => '$pathRelease'".toString())
+ podMethodLines.add("end")
+ return podMethodLines
}
/**
@@ -362,71 +471,41 @@ class XcodeTask extends DefaultTask {
* @return updated copy of Podfile (may be identical to input)
*/
@VisibleForTesting
- static List updatePodfileTarget(
- List oldPodfileLines, String xcodeTarget,
- String podNameMethod, boolean addPodMethod) {
-
- // Indent for aesthetic reasons in Podfile
- String podMethodLine = " $podNameMethod"
- List newPodfileLines = new ArrayList<>()
- boolean podMethodProcessed = false
- boolean withinXcodeTarget = false
-
- oldPodfileLines.each { String line ->
-
- // Copies each line to newPodfileLines, unless skipped
- boolean skipWritingLine = false
-
- // Find xcodeTarget within single quote marks
- if (line.contains("'$xcodeTarget'")) {
- withinXcodeTarget = true
-
- } else if (withinXcodeTarget) {
+ static List updatePodfileTargets(
+ List podfileLines,
+ List podspecDetailsList,
+ XcodeTargetDetails xcodeTargetDetails) {
- // For upgrade from v0.4.3 to v0.5.0, basically for Xcode 7
- // TODO: remove code for plugin beta release as it's not necessary after upgrading
- if (line.contains("pod 'j2objc")) {
- // Old pod lines that should be removed. Example:
- // pod 'j2objc-shared-debug', :configuration => ['Debug'], :path => '/Users/USERNAME/dev/taptap/base/build'
- skipWritingLine = true
- }
+ // Strip the following:
+ // 1) pod method calls
+ // 2) v0.4.3 and earlier inlined pod methods
+ // 3) 'platform :' lines for ios, osx & watchos
+ String stripRegex = /^\s*((j2objc_)|(pod 'j2objc)|(platform\s)).*/
- if (line.contains(podNameMethod)) {
- // skip copying this line
- skipWritingLine = true
- if (podMethodProcessed) {
- // repeated podName lines, drop them as they should not be here
- } else {
- if (addPodMethod) {
- // update existing pod method line
- // finding existing line makes for stable in place ordering
- newPodfileLines.add(podMethodLine)
- }
- // If addPodMethod = false, then this line is dropped
- podMethodProcessed = true
- }
- } else if (line.contains('end')) {
- withinXcodeTarget = false
- if (!podMethodProcessed) {
- if (addPodMethod) {
- // no existing pod method line, so add it
- newPodfileLines.add(podMethodLine)
- }
- podMethodProcessed = true
- }
- }
- }
+ List newPodfileLines =
+ regexStripLines(podfileLines, true, targetStartRegex, endRegex, stripRegex)
- if (!skipWritingLine) {
- newPodfileLines.add(line)
- }
+ List insertLines = new ArrayList<>()
+ insertLines.add(' platform :INVALID')
+ podspecDetailsList.each { PodspecDetails podspecDetails ->
+ insertLines.add(" ${podspecDetails.getPodMethodName()}".toString())
}
- if (!podMethodProcessed) {
- throw new InvalidUserDataException(
- "Unable to find Podfile target: $xcodeTarget")
+ xcodeTargetDetails.xcodeTargetsIos.each { String iosTarget ->
+ insertLines.set(0, " platform :ios, '${xcodeTargetDetails.minVersionIos}'".toString())
+ String startTargetNamed = targetNamedRegex.replace('TARGET', iosTarget)
+ newPodfileLines = regexInsertLines(newPodfileLines, true, startTargetNamed, endRegex, insertLines)
+ }
+ xcodeTargetDetails.xcodeTargetsOsx.each { String osxTarget ->
+ insertLines.set(0, " platform :osx, '${xcodeTargetDetails.minVersionOsx}'".toString())
+ String startTargetNamed = targetNamedRegex.replace('TARGET', osxTarget)
+ newPodfileLines = regexInsertLines(newPodfileLines, true, startTargetNamed, endRegex, insertLines)
+ }
+ xcodeTargetDetails.xcodeTargetsWatchos.each { String watchosTarget ->
+ insertLines.set(0, " platform :watchos, '${xcodeTargetDetails.minVersionWatchos}'".toString())
+ String startTargetNamed = targetNamedRegex.replace('TARGET', watchosTarget)
+ newPodfileLines = regexInsertLines(newPodfileLines, true, startTargetNamed, endRegex, insertLines)
}
-
return newPodfileLines
}
}
diff --git a/src/test/groovy/com/github/j2objccontrib/j2objcgradle/tasks/XcodeTaskTest.groovy b/src/test/groovy/com/github/j2objccontrib/j2objcgradle/tasks/XcodeTaskTest.groovy
index c978db2e..4a843fba 100644
--- a/src/test/groovy/com/github/j2objccontrib/j2objcgradle/tasks/XcodeTaskTest.groovy
+++ b/src/test/groovy/com/github/j2objccontrib/j2objcgradle/tasks/XcodeTaskTest.groovy
@@ -17,6 +17,7 @@
package com.github.j2objccontrib.j2objcgradle.tasks
import com.github.j2objccontrib.j2objcgradle.J2objcConfig
+import com.google.common.annotations.VisibleForTesting
import org.gradle.api.InvalidUserDataException
import org.gradle.api.Project
import org.gradle.testfixtures.ProjectBuilder
@@ -36,6 +37,17 @@ class XcodeTaskTest {
// TODO: use this within future tests
private Project proj
+ XcodeTask.XcodeTargetDetails xcodeTargetDetailsIosAppOnly =
+ new XcodeTask.XcodeTargetDetails(
+ ['IOS-APP'], [], [],
+ // Append '.0' to version number to check that it's not using defaults
+ '6.0.0', '10.4.0', '1.0.0')
+ List podspecDetailsProj =
+ [new XcodeTask.PodspecDetails(
+ 'PROJ',
+ new File('/SRC/PROJ/BUILD/j2objc-PROJ-debug.podspec'),
+ new File('/SRC/PROJ/BUILD/j2objc-PROJ-release.podspec'))]
+
@Rule
public ExpectedException expectedException = ExpectedException.none();
@@ -56,7 +68,7 @@ class XcodeTaskTest {
J2objcConfig j2objcConfig =
proj.extensions.create('j2objcConfig', J2objcConfig, proj)
j2objcConfig.xcodeProjectDir = '../ios'
- j2objcConfig.xcodeTargets = ['IOS-APP']
+ j2objcConfig.xcodeTargetsIos = ['IOS-APP']
XcodeTask j2objcXcode = (XcodeTask) proj.tasks.create(name: 'j2objcXcode', type: XcodeTask)
j2objcXcode.verifyXcodeArgs()
@@ -72,7 +84,7 @@ class XcodeTaskTest {
J2objcConfig j2objcConfig =
proj.extensions.create('j2objcConfig', J2objcConfig, proj)
assert null == j2objcConfig.xcodeProjectDir
- assert 0 == j2objcConfig.xcodeTargets.size()
+ assert 0 == j2objcConfig.xcodeTargetsIos.size()
XcodeTask j2objcXcode = (XcodeTask) proj.tasks.create(name: 'j2objcXcode', type: XcodeTask)
@@ -110,6 +122,8 @@ class XcodeTaskTest {
createJ2objcConfig: true))
j2objcConfig.xcodeProjectDir = '../ios'
+ j2objcConfig.xcodeTargetsIos = ['IOS-APP', 'IOS-APPTests']
+ j2objcConfig.minVersionIos = '6.0.0'
// Podfile Write
// This is outside of the project's temp directory but appears to work fine
@@ -117,6 +131,8 @@ class XcodeTaskTest {
File podfile = proj.file('../ios/Podfile')
podfile.deleteOnExit()
podfile.write(
+ "use_frameworks!\n" +
+ "\n" +
"target 'IOS-APP' do\n" +
"end\n" +
"\n" +
@@ -128,8 +144,8 @@ class XcodeTaskTest {
mockProjectExec.demandExecAndReturn(
proj.file('../ios').absolutePath, // working directory
[
- "pod",
- "install",
+ 'pod',
+ 'install',
],
null,
null,
@@ -151,16 +167,21 @@ class XcodeTaskTest {
String podNameRelease = "j2objc-${proj.name}-release"
String path = "../${proj.getProjectDir().getName()}/build"
List expectedPodfile = [
+ "use_frameworks!",
+ "",
+ "# J2ObjC Gradle Plugin - DO NOT MODIFY from here to the first target",
"def $podNameMethod",
" pod '$podNameDebug', :configuration => ['Debug'], :path => '$path'",
" pod '$podNameRelease', :configuration => ['Release'], :path => '$path'",
"end",
"",
"target 'IOS-APP' do",
+ " platform :ios, '6.0.0'",
" $podNameMethod",
"end",
"",
"target 'IOS-APPTests' do",
+ " platform :ios, '6.0.0'",
" $podNameMethod",
"end"]
List readPodfileLines = podfile.readLines()
@@ -177,7 +198,7 @@ class XcodeTaskTest {
createJ2objcConfig: true))
j2objcConfig.xcodeProjectDir = 'ios'
- j2objcConfig.xcodeTargets = ['IOS-APP']
+ j2objcConfig.xcodeTargetsIos = ['IOS-APP']
// Needed for podspec
proj.file(proj.buildDir).mkdir()
@@ -193,9 +214,9 @@ class XcodeTaskTest {
assert false, 'Expected Exception'
} catch (InvalidUserDataException exception) {
assert exception.toString().contains("Set xcodeProjectDir to the directory containing 'IOS-APP.xcodeproj':")
- assert exception.toString().contains("Within that directory, create the Podfile with:")
+ assert exception.toString().contains('Within that directory, create the Podfile with:')
assert exception.toString().contains("(cd ${proj.file('ios').absolutePath} && pod init)")
- assert exception.toString().contains("sudo gem install cocoapods")
+ assert exception.toString().contains('sudo gem install cocoapods')
}
// Verify no calls to project.copy, project.delete or project.exec
@@ -211,7 +232,7 @@ class XcodeTaskTest {
applyJavaPlugin: true,
createJ2objcConfig: true))
assert null == j2objcConfig.xcodeProjectDir
- assert 0 == j2objcConfig.xcodeTargets.size()
+ assert 0 == j2objcConfig.xcodeTargetsIos.size()
XcodeTask j2objcXcode = (XcodeTask) proj.tasks.create(name: 'j2objcXcode', type: XcodeTask)
@@ -257,12 +278,149 @@ class XcodeTaskTest {
}
@Test
- void testWriteUpdatedPodfileIfNeeded_Needed() {
+ void testRegexStripLines_noStartMatch() {
+ List oldLines = [
+ 'st-art',
+ 'strip',
+ 'en-d']
+
+ List newLines = XcodeTask.regexStripLines(
+ oldLines, false, /start/, /end/, /^strip$/)
+
+ assert oldLines == newLines
+ }
+
+ @Test
+ void testRegexStripLines_remove() {
+ List oldLines = [
+ 'strip outside',
+ 'start',
+ 'str-ip',
+ 'strip inside',
+ 'end']
+
+ List newLines = XcodeTask.regexStripLines(
+ oldLines, false, /start/, /end/, /strip/)
+
+ List expectedNewLines = [
+ 'strip outside',
+ 'start',
+ 'str-ip',
+ 'end']
+ assert expectedNewLines == newLines
+ }
+
+ @Test
+ void testRegexStripLines_removeInclusivePreserveEndLine() {
+ List oldLines = [
+ 'BEFORE',
+ 'start',
+ 'end',
+ 'AFTER']
+
+ List newLines = XcodeTask.regexStripLines(
+ oldLines, true, /start/, /end/, /.*/)
+
+ List expectedNewLines = [
+ 'BEFORE',
+ 'end',
+ 'AFTER']
+ assert expectedNewLines == newLines
+ }
+
+ @Test
+ void testRegexInsertLines_afterStart() {
+ List oldLines = [
+ 'start',
+ 'in-between',
+ 'end']
+
+ List insertLines = new ArrayList<>()
+ insertLines.add('line1')
+ insertLines.add('line2')
+ List newLines = XcodeTask.regexInsertLines(
+ oldLines, true, /start/, /end/, insertLines)
+
+ List expectedNewLines = [
+ 'start',
+ 'line1',
+ 'line2',
+ 'in-between',
+ 'end']
+ assert expectedNewLines == newLines
+ }
+
+ @Test
+ void testRegexInsertLines_notAfterStart() {
+ List oldLines = [
+ 'start',
+ 'in-between',
+ 'end']
+
+ List newLines = XcodeTask.regexInsertLines(
+ oldLines, false, /start/, /end/, ['line1', 'line2'])
+
+ List expectedNewLines = [
+ 'start',
+ 'in-between',
+ 'line1',
+ 'line2',
+ 'end']
+ assert expectedNewLines == newLines
+ }
+
+ @Test
+ void testRegexInsertLines_ignoreMultipleMatches() {
+ List oldLines = [
+ 'start',
+ 'end',
+ 'start',
+ 'end']
+
+ List newLines = XcodeTask.regexInsertLines(
+ oldLines, false, /start/, /end/, ['inserted'])
+
+ List expectedNewLines = [
+ 'start',
+ 'inserted',
+ 'end',
+ 'start',
+ 'end']
+ assert expectedNewLines == newLines
+ }
+
+ @Test
+ void testRegexInsertLines_noMatchStart() {
+ List oldLines = [
+ 'start',
+ 'end']
+
+ expectedException.expect(InvalidUserDataException.class)
+ expectedException.expectMessage('Failed to find startRegex: /no-match-start/')
+
+ XcodeTask.regexInsertLines(oldLines, false, /no-match-start/, /end/, new ArrayList<>())
+ }
+
+ @Test
+ void testRegexInsertLines_noMatchEnd() {
+ List oldLines = [
+ 'start',
+ 'end']
+
+ expectedException.expect(InvalidUserDataException.class)
+ expectedException.expectMessage('Failed to find endRegex: /no-match-end/')
+
+ XcodeTask.regexInsertLines(oldLines, false, /start/, /no-match-end/, new ArrayList<>())
+ }
+
+ @Test
+ void testWriteUpdatedPodfileIfNeeded_Needed_ThenNotNeeded() {
// Write temp Podfile that's deleted on exit
- File podfile = File.createTempFile("podfile","")
+ File podfile = File.createTempFile('Podfile', '')
podfile.deleteOnExit()
podfile.write(
+ "#user comment\n" +
"target 'IOS-APP' do\n" +
"end")
@@ -271,260 +429,417 @@ class XcodeTaskTest {
List podspecDetailsList = new ArrayList<>()
podspecDetailsList.add(new XcodeTask.PodspecDetails(
'PROJ',
- // It doesn't matter that these files don't exist, only their relative path to Podfile
+ // Only their relative path to Podfile matters, they don't need to exist
new File(podspecBuildDir + '/j2objc-PROJ-debug.podspec'),
new File(podspecBuildDir + '/j2objc-PROJ-release.podspec')))
XcodeTask.writeUpdatedPodfileIfNeeded(
- podspecDetailsList, ['IOS-APP'], podfile, null)
+ podspecDetailsList, xcodeTargetDetailsIosAppOnly, podfile, null)
// Verify modified Podfile
List expectedLines = [
+ "#user comment",
+ "# J2ObjC Gradle Plugin - DO NOT MODIFY from here to the first target",
"def j2objc_PROJ",
" pod 'j2objc-PROJ-debug', :configuration => ['Debug'], :path => '../PROJ/BUILD'",
" pod 'j2objc-PROJ-release', :configuration => ['Release'], :path => '../PROJ/BUILD'",
"end",
"",
"target 'IOS-APP' do",
+ " platform :ios, '6.0.0'",
" j2objc_PROJ",
"end"]
List readPodfileLines = podfile.readLines()
assert expectedLines == readPodfileLines
+
+ // Verify unmodified on second call
+ // TODO: verify that file wasn't written a second time
+ XcodeTask.writeUpdatedPodfileIfNeeded(
+ podspecDetailsList, xcodeTargetDetailsIosAppOnly, podfile, null)
+ readPodfileLines = podfile.readLines()
+ assert expectedLines == readPodfileLines
}
@Test
- void testWriteUpdatedPodfileIfNeeded_NotNeeded() {
+ void testUpdatePodfile_basic() {
+ List podfileLines = [
+ "target 'IOS-APP' do",
+ "end"]
- // Write temp Podfile that's deleted on exit
- List writtenLines = [
- "def j2objc_PROJ",
- " pod 'j2objc-PROJ-debug', :configuration => ['Debug'], :path => '../PROJ/BUILD'",
- " pod 'j2objc-PROJ-release', :configuration => ['Release'], :path => '../PROJ/BUILD'",
- "end",
- "",
- "target 'IOS-APP' do",
- " j2objc_PROJ",
- "end"]
- File podfile = File.createTempFile("podfile","")
- podfile.deleteOnExit()
- podfile.write(writtenLines.join('\n'))
+ List newPodfileLines = XcodeTask.updatePodfile(
+ podfileLines,
+ podspecDetailsProj,
+ xcodeTargetDetailsIosAppOnly,
+ new File('/SRC/ios/Podfile'),
+ null)
- // Update the Podfile
- String podspecBuildDir = podfile.getParentFile().getParentFile().toString() + '/PROJ/BUILD'
- List podspecDetailsList = new ArrayList<>()
- podspecDetailsList.add(new XcodeTask.PodspecDetails(
- 'PROJ',
- new File(podspecBuildDir + '/j2objc-PROJ-debug.podspec'),
- new File(podspecBuildDir + '/j2objc-PROJ-release.podspec')))
- XcodeTask.writeUpdatedPodfileIfNeeded(
- podspecDetailsList, ['IOS-APP'], podfile, null)
+ List expectedPodfileLines = [
+ "# J2ObjC Gradle Plugin - DO NOT MODIFY from here to the first target",
+ "def j2objc_PROJ",
+ " pod 'j2objc-PROJ-debug', :configuration => ['Debug'], :path => '../PROJ/BUILD'",
+ " pod 'j2objc-PROJ-release', :configuration => ['Release'], :path => '../PROJ/BUILD'",
+ "end",
+ "",
+ "target 'IOS-APP' do",
+ " platform :ios, '6.0.0'",
+ " j2objc_PROJ",
+ "end"]
+ assert expectedPodfileLines == newPodfileLines
- // Missing verification that the file wasn't written but verifies it's the same as before
- List readPodfileLines = podfile.readLines()
- assert writtenLines == readPodfileLines
+ // Second time around is a no-op
+ newPodfileLines = XcodeTask.updatePodfile(
+ newPodfileLines,
+ podspecDetailsProj,
+ xcodeTargetDetailsIosAppOnly,
+ new File('/SRC/ios/Podfile'),
+ null)
+ assert expectedPodfileLines == newPodfileLines
}
@Test
- void testUpdatePodfile_Complex() {
- // 1) Clean up pod method
- // 2) Add pod method to IOS-APP target
- // 3) Remove pod method from IOS-APPTest target
+ void testUpdatePodfile_complex() {
List podfileLines = [
- "def j2objc_PROJ",
- " RANDOM-CRUFT-TO-BE-DELETED",
- " pod 'j2objc-PROJ-IGNORE', :configuration => ['Release'], :path => '/WRONG-DIR'",
- "end",
+ "# user comment",
"",
"target 'IOS-APP' do",
- "",
- " pod 'IGNORE1', :path => 'IGNORE'",
"end",
- "",
- "target 'IOS-APP WatchKit App' do",
- " j2objc_PROJ",
- " pod 'IGNORE2', :path => 'IGNORE'",
+ "target 'OSX-APP' do",
+ " j2objc_JUNK_TO_BE_DELETED",
+ "end",
+ "target 'WATCH-APP' do",
"end"]
+ XcodeTask.XcodeTargetDetails xcodeTargetDetails = new XcodeTask.XcodeTargetDetails(
+ ['IOS-APP'], ['OSX-APP'], ['WATCH-APP'],
+ '6.0.0', '10.4.0', '1.0.0')
List newPodfileLines = XcodeTask.updatePodfile(
podfileLines,
- new XcodeTask.PodspecDetails(
- 'PROJ',
- new File('/SRC/PROJ/BUILD/j2objc-PROJ-debug.podspec'),
- new File('/SRC/PROJ/BUILD/j2objc-PROJ-release.podspec')),
- ['IOS-APP'],
+ podspecDetailsProj,
+ xcodeTargetDetails,
new File('/SRC/ios/Podfile'),
null)
- List expectedLines = [
+ List expectedPodfileLines = [
+ "# user comment",
+ "",
+ "# J2ObjC Gradle Plugin - DO NOT MODIFY from here to the first target",
"def j2objc_PROJ",
" pod 'j2objc-PROJ-debug', :configuration => ['Debug'], :path => '../PROJ/BUILD'",
" pod 'j2objc-PROJ-release', :configuration => ['Release'], :path => '../PROJ/BUILD'",
"end",
"",
"target 'IOS-APP' do",
- "",
- " pod 'IGNORE1', :path => 'IGNORE'",
+ " platform :ios, '6.0.0'",
" j2objc_PROJ",
"end",
- "",
- "target 'IOS-APP WatchKit App' do",
- " pod 'IGNORE2', :path => 'IGNORE'",
+ "target 'OSX-APP' do",
+ " platform :osx, '10.4.0'",
+ " j2objc_PROJ",
+ "end",
+ "target 'WATCH-APP' do",
+ " platform :watchos, '1.0.0'",
+ " j2objc_PROJ",
"end"]
+ assert expectedPodfileLines == newPodfileLines
- assert expectedLines == newPodfileLines
+ // Second time around is a no-op
+ newPodfileLines = XcodeTask.updatePodfile(
+ newPodfileLines,
+ podspecDetailsProj,
+ xcodeTargetDetails,
+ new File('/SRC/ios/Podfile'),
+ null)
+ assert expectedPodfileLines == newPodfileLines
+ }
+
+ @Test
+ void testUpdatePodfile_needJ2objcConfig() {
+ List podfileLines = [
+ "target 'IOS-APP' do",
+ "end",
+ "target 'WATCH-APP' do",
+ "end"]
+
+ expectedException.expect(InvalidUserDataException.class)
+ expectedException.expectMessage("You must configure the xcode targets for the J2ObjC Gradle Plugin")
+ expectedException.expectMessage("It must be a subset of the valid targets: 'IOS-APP', 'WATCH-APP'")
+ expectedException.expectMessage("xcodeTargetsIos 'IOS-APP', 'IOS-APPTests' // example")
+
+ XcodeTask.updatePodfile(
+ podfileLines,
+ [],
+ new XcodeTask.XcodeTargetDetails(
+ [], [], [],
+ '6.0.0', '10.4.0', '1.0.0'),
+ null,
+ null)
}
@Test
- // If xcodeTargets == [], then include all targets
- void testUpdatePodfile_DefaultsToAllTargets() {
+ void testUpdatePodfile_invalidTarget() {
List podfileLines = [
"target 'IOS-APP' do",
- " pod 'IGNORE1', :path => 'IGNORE'",
"end",
+ "target 'WATCH-APP' do",
+ "end"]
+
+ expectedException.expect(InvalidUserDataException.class)
+ expectedException.expectMessage("Invalid j2objcConfig { xcodeTargetsIos 'TARGET-DOES-NOT-EXIST' }")
+ expectedException.expectMessage("Must be one of the valid targets: 'IOS-APP', 'WATCH-APP'")
+
+ XcodeTask.updatePodfile(
+ podfileLines,
+ [],
+ new XcodeTask.XcodeTargetDetails(
+ ['TARGET-DOES-NOT-EXIST'], [], [],
+ '6.0.0', '10.4.0', '1.0.0'),
+ null,
+ null)
+ }
+
+ @Test
+ void testUpdatePodMethods_basic() {
+ List podfileLines = [
+ "# user comment",
"",
- "target 'IOS-APPTests' do",
- " pod 'IGNORE2', :path => 'IGNORE'",
+ // "# J2ObjC Gradle Plugin..." line is missing to make sure regex handles both cases
+ "def j2objc_TO_BE_DELETED",
+ " pod 'j2objc-TO_BE_DELETED-debug', :configuration => ['Debug'], :path => '../shared/build'",
+ " pod 'j2objc-TO_BE_DELETED-release', :configuration => ['Release'], :path => '../shared/build'",
"end",
"",
- "target 'IOS-APP WatchKit App' do",
- " j2objc_PROJ",
- " pod 'IGNORE3', :path => 'IGNORE'",
+ "target 'IOS-APP' do",
"end"]
- List newPodfileLines = XcodeTask.updatePodfile(
+ List newPodfileLines = XcodeTask.updatePodMethods(
podfileLines,
- new XcodeTask.PodspecDetails(
- 'PROJ',
- new File('/SRC/PROJ/BUILD/j2objc-PROJ-debug.podspec'),
- new File('/SRC/PROJ/BUILD/j2objc-PROJ-release.podspec')),
- [], // xcodeTargets is empty to test default of all targets
- new File('/SRC/ios/Podfile'),
- null)
+ podspecDetailsProj,
+ new File('/SRC/ios/Podfile'))
List expectedLines = [
+ "# user comment",
+ "",
+ "# J2ObjC Gradle Plugin - DO NOT MODIFY from here to the first target",
"def j2objc_PROJ",
" pod 'j2objc-PROJ-debug', :configuration => ['Debug'], :path => '../PROJ/BUILD'",
" pod 'j2objc-PROJ-release', :configuration => ['Release'], :path => '../PROJ/BUILD'",
"end",
"",
"target 'IOS-APP' do",
- " pod 'IGNORE1', :path => 'IGNORE'",
- " j2objc_PROJ",
+ "end"]
+
+ assert expectedLines == newPodfileLines
+ }
+
+ @Test
+ void testUpdatePodMethods() {
+ List podfileLines = [
+ "# user comment",
+ "",
+ "# J2ObjC Gradle Plugin - DO NOT MODIFY from this line to the first target",
+ "def j2objc_TO_BE_DELETED",
+ " pod 'j2objc-TO_BE_DELETED-debug', :configuration => ['Debug'], :path => '../shared/build'",
+ " pod 'j2objc-TO_BE_DELETED-release', :configuration => ['Release'], :path => '../shared/build'",
"end",
"",
- "target 'IOS-APPTests' do",
- " pod 'IGNORE2', :path => 'IGNORE'",
- " j2objc_PROJ",
+ "",
+ "target 'IOS-APP' do",
+ " j2objc_DELETED_BY_ANOTHER_METHOD",
+ "end"]
+
+ List newPodfileLines = XcodeTask.updatePodMethods(
+ podfileLines,
+ [new XcodeTask.PodspecDetails(
+ 'PROJA',
+ new File('/SRC/PROJA/BUILD/j2objc-PROJA-debug.podspec'),
+ new File('/SRC/PROJA/BUILD/j2objc-PROJB-release.podspec')),
+ new XcodeTask.PodspecDetails(
+ 'PROJB',
+ new File('/SRC/PROJB/BUILD/j2objc-PROJB-debug.podspec'),
+ new File('/SRC/PROJB/BUILD/j2objc-PROJB-release.podspec'))],
+ new File('/SRC/ios/Podfile'))
+
+ List expectedLines = [
+ "# user comment",
+ "",
+ "# J2ObjC Gradle Plugin - DO NOT MODIFY from here to the first target",
+ "def j2objc_PROJA",
+ " pod 'j2objc-PROJA-debug', :configuration => ['Debug'], :path => '../PROJA/BUILD'",
+ " pod 'j2objc-PROJB-release', :configuration => ['Release'], :path => '../PROJA/BUILD'",
"end",
"",
- "target 'IOS-APP WatchKit App' do",
- " j2objc_PROJ",
- " pod 'IGNORE3', :path => 'IGNORE'",
+ "def j2objc_PROJB",
+ " pod 'j2objc-PROJB-debug', :configuration => ['Debug'], :path => '../PROJB/BUILD'",
+ " pod 'j2objc-PROJB-release', :configuration => ['Release'], :path => '../PROJB/BUILD'",
+ "end",
+ "",
+ "target 'IOS-APP' do",
+ " j2objc_DELETED_BY_ANOTHER_METHOD",
"end"]
assert expectedLines == newPodfileLines
}
- @Test(expected = InvalidUserDataException.class)
- void testUpdatePodfileTarget_TargetNotFound() {
- List podfileLines = [
- "target 'IOS-APP' do",
- "pod 'j2objc-PROJ-debug', :path => '/Users/USERNAME/dev/workspace/shared/build'",
+ @Test
+ void testPodMethodLines() {
+ List podMethodLines = XcodeTask.podMethodLines(
+ podspecDetailsProj.get(0),
+ new File('/SRC/ios/Podfile'))
+
+ List expectedLines = [
+ "def j2objc_PROJ",
+ " pod 'j2objc-PROJ-debug', :configuration => ['Debug'], :path => '../PROJ/BUILD'",
+ " pod 'j2objc-PROJ-release', :configuration => ['Release'], :path => '../PROJ/BUILD'",
"end"]
- XcodeTask.updatePodfileTarget(
- podfileLines, 'XCODE_TARGET_DOES_NOT_EXIST',
- 'j2objc_PROJ', true)
+ assert expectedLines == podMethodLines
}
@Test
- void testUpdatePodfileTarget_AddAndRemove() {
- List podfileTargetEmpty = [
+ void testUpdatePodfileTargets_basic() {
+ List podfileLines = [
"target 'IOS-APP' do",
+ "end",
+ "target 'IOS-APP-B' do",
"end"]
- List podfileTargetWithMethod = [
+ // Add 1st target
+ List newPodfileLines = XcodeTask.updatePodfileTargets(
+ podfileLines,
+ podspecDetailsProj,
+ xcodeTargetDetailsIosAppOnly)
+ List expectedPodfileLines = [
"target 'IOS-APP' do",
+ " platform :ios, '6.0.0'",
" j2objc_PROJ",
+ "end",
+ "target 'IOS-APP-B' do",
"end"]
+ assert expectedPodfileLines == newPodfileLines
+
+ // Repeated call is noop
+ newPodfileLines = XcodeTask.updatePodfileTargets(
+ newPodfileLines,
+ podspecDetailsProj,
+ xcodeTargetDetailsIosAppOnly)
+ assert expectedPodfileLines == newPodfileLines
- // Remove no-op
- List newPodfileLines = XcodeTask.updatePodfileTarget(
- podfileTargetEmpty, 'IOS-APP', 'j2objc_PROJ', false)
- assert newPodfileLines == newPodfileLines
-
- // Add
- newPodfileLines = XcodeTask.updatePodfileTarget(
- podfileTargetEmpty, 'IOS-APP', 'j2objc_PROJ', true)
- assert podfileTargetWithMethod == newPodfileLines
-
- // Add no-op
- newPodfileLines = XcodeTask.updatePodfileTarget(
- podfileTargetEmpty, 'IOS-APP', 'j2objc_PROJ', true)
- assert podfileTargetWithMethod == newPodfileLines
-
- // Remove
- newPodfileLines = XcodeTask.updatePodfileTarget(
- podfileTargetEmpty, 'IOS-APP', 'j2objc_PROJ', false)
- assert newPodfileLines == newPodfileLines
+ // Swap to 2nd target
+ newPodfileLines = XcodeTask.updatePodfileTargets(
+ newPodfileLines,
+ podspecDetailsProj,
+ new XcodeTask.XcodeTargetDetails(
+ ['IOS-APP-B'], [], [],
+ '6.0.0', '10.4.0', '1.0.0'))
+ List expectedPodfileLinesAfterSwap = [
+ "target 'IOS-APP' do",
+ "end",
+ "target 'IOS-APP-B' do",
+ " platform :ios, '6.0.0'",
+ " j2objc_PROJ",
+ "end"]
+ assert expectedPodfileLinesAfterSwap == newPodfileLines
}
@Test
- void testUpdatePodfileTarget_PreserveOrdering() {
+ void testUpdatePodfileTargets_allPlatformsMultipleProjectsAndTests() {
List podfileLines = [
- "target 'TARGET_A' do",
- " pod 'IGNORE1', :path => 'IGNORE'",
- " j2objc_PROJ",
+ // pod method should not be affected by removal of the old code
+ "target 'IOS-APP' do",
"end",
- "",
- "target 'TARGET_B' do",
- " j2objc_PROJ",
- " pod 'IGNORE2', :path => 'IGNORE'",
+ "target 'IOS-APPTests' do",
+ "end",
+ "target 'OSX-APP' do",
+ "end",
+ "target 'OSX-APPTests' do",
+ "end",
+ "target 'WATCH-APP' do",
+ "end",
+ "target 'WATCH-APPTests' do",
"end"]
- List newPodfileLines = XcodeTask.updatePodfileTarget(
- podfileLines, 'TARGET_A', 'j2objc_PROJ', true)
- newPodfileLines = XcodeTask.updatePodfileTarget(
- newPodfileLines, 'TARGET_B', 'j2objc_PROJ', true)
+ // Update podfile targets
+ List newPodfileLines = XcodeTask.updatePodfileTargets(
+ podfileLines,
+ [new XcodeTask.PodspecDetails('PROJ_A', null, null),
+ new XcodeTask.PodspecDetails('PROJ_B', null, null)],
+ new XcodeTask.XcodeTargetDetails(
+ ['IOS-APP', 'IOS-APPTests'], ['OSX-APP', 'OSX-APPTests'], ['WATCH-APP', 'WATCH-APPTests'],
+ '6.0.0', '10.4.0', '1.0.0'))
- // Preserves the ordering of the lines
- assert podfileLines == newPodfileLines
+ List expectedPodfileLines = [
+ "target 'IOS-APP' do",
+ " platform :ios, '6.0.0'",
+ " j2objc_PROJ_A",
+ " j2objc_PROJ_B",
+ "end",
+ "target 'IOS-APPTests' do",
+ " platform :ios, '6.0.0'",
+ " j2objc_PROJ_A",
+ " j2objc_PROJ_B",
+ "end",
+ "target 'OSX-APP' do",
+ " platform :osx, '10.4.0'",
+ " j2objc_PROJ_A",
+ " j2objc_PROJ_B",
+ "end",
+ "target 'OSX-APPTests' do",
+ " platform :osx, '10.4.0'",
+ " j2objc_PROJ_A",
+ " j2objc_PROJ_B",
+ "end",
+ "target 'WATCH-APP' do",
+ " platform :watchos, '1.0.0'",
+ " j2objc_PROJ_A",
+ " j2objc_PROJ_B",
+ "end",
+ "target 'WATCH-APPTests' do",
+ " platform :watchos, '1.0.0'",
+ " j2objc_PROJ_A",
+ " j2objc_PROJ_B",
+ "end"]
+ assert expectedPodfileLines == newPodfileLines
}
@Test
- // For upgrade from v0.4.3 to v0.5.0
- void testUpdatePodfileTarget_PodMethodUpgrade() {
+ void testUpdatePodfileTargets_ignoreExistingLines() {
List podfileLines = [
- // pod method should not be affected by removal of the old code
- "def j2objc_PROJ",
- " pod 'j2objc-PROJ-debug', :configuration => ['Debug'], :path => '/Users/USERNAME/dev/workspace/shared/build'",
- " pod 'j2objc-PROJ-release', :configuration => ['Release'], :path => '/Users/USERNAME/dev/workspace/shared/build'",
- "end",
- "",
- "target 'TARGET' do",
+ "target 'IOS-APP' do",
+ // Existing lines should be ignored
+ " pod 'IGNORE1', :path => 'IGNORE1'",
+ " pod 'IGNORE2', :path => 'IGNORE2'",
+ // v0.4.3 upgrade to discard old inlining of pod method
" pod 'j2objc-PROJ-debug', :configuration => ['Debug'], :path => '/Users/USERNAME/dev/workspace/shared/build'",
" pod 'j2objc-PROJ-release', :configuration => ['Release'], :path => '/Users/USERNAME/dev/workspace/shared/build'",
- " pod 'IGNORE2', :path => 'IGNORE'",
"end"]
+ // Update podfile targets
+ List newPodfileLines = XcodeTask.updatePodfileTargets(
+ podfileLines,
+ podspecDetailsProj,
+ xcodeTargetDetailsIosAppOnly)
+
List expectedPodfileLines = [
- "def j2objc_PROJ",
- " pod 'j2objc-PROJ-debug', :configuration => ['Debug'], :path => '/Users/USERNAME/dev/workspace/shared/build'",
- " pod 'j2objc-PROJ-release', :configuration => ['Release'], :path => '/Users/USERNAME/dev/workspace/shared/build'",
- "end",
- "",
- "target 'TARGET' do",
- " pod 'IGNORE2', :path => 'IGNORE'",
+ "target 'IOS-APP' do",
+ " platform :ios, '6.0.0'",
" j2objc_PROJ",
+ " pod 'IGNORE1', :path => 'IGNORE1'",
+ " pod 'IGNORE2', :path => 'IGNORE2'",
"end"]
-
- // First update cleans up the Podfile, replacing within targets definitions with pod method
- List newPodfileLines = XcodeTask.updatePodfileTarget(
- podfileLines, 'TARGET', 'j2objc_PROJ', true)
assert expectedPodfileLines == newPodfileLines
+ }
- // Second update has no effect
- newPodfileLines = XcodeTask.updatePodfileTarget(
- newPodfileLines, 'TARGET', 'j2objc_PROJ', true)
- assert expectedPodfileLines == newPodfileLines
+ // Better error is given in parent call
+ @Test(expected = InvalidUserDataException.class)
+ void testUpdatePodfileTargets_TargetNotFound() {
+ List podfileLines = [
+ "target 'IOS-APP' do",
+ "end"]
+
+ XcodeTask.updatePodfileTargets(
+ podfileLines,
+ podspecDetailsProj,
+ new XcodeTask.XcodeTargetDetails(
+ ['TARGET-DOES-NOT-EXIST'], [], [],
+ '6.0.0', '10.4.0', '1.0.0'))
}
}