-
Notifications
You must be signed in to change notification settings - Fork 43
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
Config to only add j2objc_shared method to Podfile #565
Changes from all commits
86004d5
8afd2b6
4f8d7ed
1aa92c7
605b623
555bfad
36e8d3c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,10 +49,15 @@ class XcodeTask extends DefaultTask { | |
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*/ | ||
public static final String sourceLineRegex = /^source 'http.*Specs.git'$/ // https://guides.cocoapods.org/syntax/podfile.html#podfile | ||
public static final String platformLineRegex = /^platform :.*/ | ||
|
||
@Input @Optional | ||
String getXcodeProjectDir() { return J2objcConfig.from(project).xcodeProjectDir } | ||
|
||
@Input | ||
boolean getXcodeTargetsManualConfig() { return J2objcConfig.from(project).xcodeTargetsManualConfig } | ||
|
||
boolean isTaskActive() { return getXcodeProjectDir() != null } | ||
|
||
@Input | ||
|
@@ -200,7 +205,7 @@ class XcodeTask extends DefaultTask { | |
getXcodeTargetsIos(), getXcodeTargetsOsx(), getXcodeTargetsWatchos(), | ||
getMinVersionIos(), getMinVersionOsx(), getMinVersionWatchos()) | ||
|
||
writeUpdatedPodfileIfNeeded(podspecDetailsList, xcodeTargetDetails, podfile) | ||
writeUpdatedPodfileIfNeeded(podspecDetailsList, xcodeTargetDetails, xcodeTargetsManualConfig, podfile) | ||
|
||
// install the pod | ||
ByteArrayOutputStream stdout = new ByteArrayOutputStream() | ||
|
@@ -316,6 +321,41 @@ class XcodeTask extends DefaultTask { | |
return result | ||
} | ||
|
||
/** | ||
* Replaces lines between two regexps | ||
*/ | ||
@VisibleForTesting | ||
static List<String> regexReplaceLines(List<String> podfileLines, | ||
String startRegex, String endRegex, List<String> newPodFileLines) { | ||
List<String> result = new ArrayList<>() | ||
boolean active = false | ||
boolean endOfRegex = false | ||
|
||
for (line in podfileLines) { | ||
if (!active && (line =~ startRegex)) { | ||
active = true | ||
result.addAll(newPodFileLines) | ||
} | ||
if (active && (line =~ endRegex)) { | ||
active = false | ||
endOfRegex = true | ||
} | ||
if (!active && !endOfRegex) { | ||
result.add(line) | ||
} | ||
|
||
if(endOfRegex){ | ||
endOfRegex=false | ||
} | ||
} | ||
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. | ||
* | ||
|
@@ -368,20 +408,131 @@ class XcodeTask extends DefaultTask { | |
return result | ||
} | ||
|
||
/** | ||
* Searches for the line where to insert new methods into the podfile | ||
*/ | ||
@VisibleForTesting | ||
static int findInsertLine(List<String> podfileLines) { | ||
|
||
boolean noneCommentLineFound =false | ||
boolean platformStatementFound =false | ||
boolean sourceStatementFound =false | ||
|
||
int counter = 0 | ||
int insertLineNumber = 0 | ||
for (line in podfileLines) { | ||
|
||
// if a target statement is found. insert before this statement | ||
if(line =~ targetStartRegex) { | ||
return counter | ||
} | ||
|
||
counter++ | ||
|
||
// else insert after platform statement (platform :ios, '6.0') | ||
if(platformStatementFound) continue | ||
if(line =~ platformLineRegex) { | ||
insertLineNumber = counter | ||
platformStatementFound = true | ||
continue | ||
} | ||
|
||
// else insert after platform statement (source 'https://github.com/CocoaPods/Specs.git') | ||
if(sourceStatementFound) continue | ||
if(line =~ sourceLineRegex) { | ||
insertLineNumber = counter | ||
sourceStatementFound = true | ||
continue | ||
} | ||
|
||
// else insert at first none commented line | ||
if(noneCommentLineFound) continue | ||
|
||
if(!line.trim().startsWith("#")){ | ||
insertLineNumber = counter-1 | ||
noneCommentLineFound = true | ||
} | ||
|
||
} | ||
|
||
return insertLineNumber | ||
} | ||
|
||
/** | ||
* Insert new lines in to podfile at a certain line | ||
* @param surroundWithEmptyLines regulates if inserted lines should be surrounded with empty ones | ||
* | ||
*/ | ||
@VisibleForTesting | ||
static List<String> insertAtLineNumber(List<String> podfileLines,List<String> insertLines, int line, boolean surroundWithEmptyLines) { | ||
List<String> result = new ArrayList<>() | ||
result.addAll(podfileLines.subList(0,line)) | ||
|
||
assert podfileLines.size() >= line | ||
|
||
boolean insertAtTheEnd = podfileLines.size()==line | ||
boolean insertAtTheBeginning = line==0 | ||
|
||
if(surroundWithEmptyLines){ | ||
if(!insertAtTheBeginning){ | ||
if(!isBlankLine(podfileLines,line-1)){ | ||
result.add('') | ||
} | ||
if(isBlankLine(podfileLines,line)){ | ||
line++ | ||
} | ||
} | ||
if(!insertAtTheEnd){ | ||
insertLines.add('') | ||
if(isBlankLine(podfileLines,line)){ | ||
line++ | ||
} | ||
} | ||
} | ||
result.addAll(insertLines) | ||
if(!insertAtTheEnd){ | ||
result.addAll(podfileLines.subList(line,podfileLines.size())) | ||
} | ||
return result | ||
} | ||
|
||
static boolean isBlankLine(List<String> podfileLines,int line){ | ||
if(line>=podfileLines.size()){ | ||
return false | ||
} | ||
return podfileLines.get(line).trim()=='' | ||
} | ||
|
||
/** | ||
* Checks if Podfile contains a certain regex | ||
* | ||
*/ | ||
@VisibleForTesting | ||
static boolean containsRegex(List<String> podfileLines, String startRegex) { | ||
|
||
for (line in podfileLines) { | ||
if ((line =~ startRegex).find()) { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
/** | ||
* Modify in place the existing podfile. | ||
*/ | ||
@VisibleForTesting | ||
static void writeUpdatedPodfileIfNeeded( | ||
List<PodspecDetails> podspecDetailsList, | ||
XcodeTargetDetails xcodeTargetDetails, | ||
boolean xcodeTargetsManualConfig, | ||
File podfile) { | ||
|
||
List<String> oldPodfileLines = podfile.readLines() | ||
List<String> newPodfileLines = new ArrayList<String>(oldPodfileLines) | ||
|
||
newPodfileLines = updatePodfile( | ||
newPodfileLines, podspecDetailsList, xcodeTargetDetails, podfile) | ||
newPodfileLines, podspecDetailsList, xcodeTargetDetails, xcodeTargetsManualConfig, podfile) | ||
|
||
// Write file only if it's changed | ||
if (!oldPodfileLines.equals(newPodfileLines)) { | ||
|
@@ -394,33 +545,46 @@ class XcodeTask extends DefaultTask { | |
List<String> podfileLines, | ||
List<PodspecDetails> podspecDetailsList, | ||
XcodeTargetDetails xcodeTargetDetails, | ||
boolean xcodeTargetsManualConfig, | ||
File podfile) { | ||
|
||
List<String> podfileTargets = extractXcodeTargets(podfileLines) | ||
verifyTargets(xcodeTargetDetails.xcodeTargetsIos, podfileTargets, 'xcodeTargetsIos') | ||
verifyTargets(xcodeTargetDetails.xcodeTargetsOsx, podfileTargets, 'xcodeTargetsOsx') | ||
verifyTargets(xcodeTargetDetails.xcodeTargetsWatchos, podfileTargets, 'xcodeTargetsWatchos') | ||
List<String> newPodfileLines = podfileLines; | ||
|
||
if (xcodeTargetDetails.xcodeTargetsIos.isEmpty() && | ||
xcodeTargetDetails.xcodeTargetsOsx.isEmpty() && | ||
xcodeTargetDetails.xcodeTargetsWatchos.isEmpty()) { | ||
// Give example for configuring iOS as that's the common case | ||
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") | ||
boolean xcodeTargetsAllEmpty = | ||
xcodeTargetDetails.xcodeTargetsIos.isEmpty() && | ||
xcodeTargetDetails.xcodeTargetsOsx.isEmpty() && | ||
xcodeTargetDetails.xcodeTargetsWatchos.isEmpty() | ||
|
||
if (xcodeTargetsManualConfig) { | ||
if (!xcodeTargetsAllEmpty) { | ||
throw new InvalidUserDataException( | ||
"Xcode targets must all be blank when using xcodeTargetsManualConfig.\n" + | ||
"Please update j2objcConfig by removing xcodeTargetsIos, xcodeTargetsOsx & xcodeTargetsWatchos") | ||
} | ||
} else { | ||
// xcodeTargetsManualConfig = false (default) | ||
List<String> podfileTargets = extractXcodeTargets(podfileLines) | ||
verifyTargets(xcodeTargetDetails.xcodeTargetsIos, podfileTargets, 'xcodeTargetsIos') | ||
verifyTargets(xcodeTargetDetails.xcodeTargetsOsx, podfileTargets, 'xcodeTargetsOsx') | ||
verifyTargets(xcodeTargetDetails.xcodeTargetsWatchos, podfileTargets, 'xcodeTargetsWatchos') | ||
|
||
if (xcodeTargetsAllEmpty) { | ||
// Give example for configuring iOS as that's the common case | ||
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") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add additional line:
|
||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rewrite logic so that it forces xcode targets to be empty when doing manual config. It should be either or when configuring this.
|
||
newPodfileLines = updatePodfileTargets(newPodfileLines, podspecDetailsList, xcodeTargetDetails) | ||
} | ||
|
||
// update pod methods | ||
List<String> newPodfileLines = updatePodMethods(podfileLines, podspecDetailsList, podfile) | ||
|
||
// update pod targets | ||
newPodfileLines = updatePodfileTargets(newPodfileLines, podspecDetailsList, xcodeTargetDetails) | ||
newPodfileLines = updatePodMethods(newPodfileLines, podspecDetailsList, podfile) | ||
|
||
return newPodfileLines | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the
|
||
|
@@ -430,7 +594,8 @@ class XcodeTask extends DefaultTask { | |
if (! podfileTargets.contains(xcodeTarget)) { | ||
throw new InvalidUserDataException( | ||
"Invalid j2objcConfig { $xcodeTargetsName '$xcodeTarget' }\n" + | ||
"Must be one of the valid targets: '${podfileTargets.join("', '")}'") | ||
"Must be one of the valid targets: '${podfileTargets.join("', '")}'\n" + | ||
"NOTE: if your Podfile is too complex, you may need to use xcodeTargetsManualConfig") | ||
} | ||
} | ||
} | ||
|
@@ -439,10 +604,6 @@ class XcodeTask extends DefaultTask { | |
static List<String> updatePodMethods( | ||
List<String> podfileLines, List<PodspecDetails> podspecDetailsList, File podfile) { | ||
|
||
// strip all old methods | ||
// Note: use of preserveEndLine=true so that the targetStartRegex isn't removed | ||
List<String> newPodfileLines = | ||
regexStripLines(podfileLines, false, podMethodStartRegex, targetStartRegex, /.*/) | ||
|
||
// create new methods | ||
List<String> insertLines = new ArrayList<>() | ||
|
@@ -452,10 +613,16 @@ class XcodeTask extends DefaultTask { | |
insertLines.add('') | ||
} | ||
|
||
// insert new methods immediately before first target | ||
newPodfileLines = regexInsertLines(newPodfileLines, false, /.*/, targetStartRegex, insertLines) | ||
// remove last empty line | ||
insertLines.remove(insertLines.size()-1) | ||
|
||
if(containsRegex(podfileLines,podMethodStartRegex)){ | ||
return regexReplaceLines(podfileLines, podMethodStartRegex, endRegex, insertLines) | ||
}else { | ||
int lineNr = findInsertLine(podfileLines) | ||
return insertAtLineNumber(podfileLines, insertLines, lineNr, true) | ||
} | ||
|
||
return newPodfileLines | ||
} | ||
|
||
@VisibleForTesting | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a variation of the regexInsertLines method. Just extend regexInsertLines, to add a
boolean replace
parameter. If true, it should skip copying the old lines. It avoid having duplication of similar code.