aboutsummaryrefslogtreecommitdiffstats
path: root/sdkmanager
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2011-08-22 20:10:38 -0700
committerXavier Ducrohet <xav@android.com>2011-08-22 20:39:53 -0700
commit69ff1318c8d44fc1cad0aab76a80f1804a807373 (patch)
treef4cb2fed21f34d71042a1a362a88593bd1d51984 /sdkmanager
parent9aa55ba53817062f7423dbc69716020bd052c394 (diff)
downloadsdk-69ff1318c8d44fc1cad0aab76a80f1804a807373.zip
sdk-69ff1318c8d44fc1cad0aab76a80f1804a807373.tar.gz
sdk-69ff1318c8d44fc1cad0aab76a80f1804a807373.tar.bz2
Modify android create/update project to deal with new build.xml
New mechanism to embed a build version into build.xml to figure out whether the build.xml file is obsolete or not. Use the version-tag: custom case to prevent erase user modifications. Fixed some issues with the name of the project (put in build.xml) for test projects which don't have any activity. Change-Id: Ib0333d15ca9558fffe24a718e704fcf4176c9014
Diffstat (limited to 'sdkmanager')
-rw-r--r--sdkmanager/app/src/com/android/sdkmanager/Main.java2
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java201
2 files changed, 141 insertions, 62 deletions
diff --git a/sdkmanager/app/src/com/android/sdkmanager/Main.java b/sdkmanager/app/src/com/android/sdkmanager/Main.java
index c3b126a..7afa66a 100644
--- a/sdkmanager/app/src/com/android/sdkmanager/Main.java
+++ b/sdkmanager/app/src/com/android/sdkmanager/Main.java
@@ -1423,7 +1423,7 @@ public class Main {
}
/**
- * Reads the line from the input stream.
+ * Reads a line from the input stream.
* @param buffer
* @throws IOException
*/
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java
index e2874b9..200e392 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java
@@ -39,6 +39,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.xpath.XPath;
@@ -53,6 +54,9 @@ import javax.xml.xpath.XPathFactory;
*/
public class ProjectCreator {
+ /** Version of the build.xml. Stored in version-tag */
+ private final static int MIN_BUILD_VERSION_TAG = 1;
+
/** Package path substitution string used in template files, i.e. "PACKAGE_PATH" */
private final static String PH_JAVA_FOLDER = "PACKAGE_PATH";
/** Package name substitution string used in template files, i.e. "PACKAGE" */
@@ -75,6 +79,11 @@ public class ProjectCreator {
private final static String PH_PROJECT_NAME = "PROJECT_NAME";
/** Application icon substitution string used in the manifest template */
private final static String PH_ICON = "ICON";
+ /** Version tag name substitution string used in template files, i.e. "VERSION_TAG". */
+ private final static String PH_VERSION_TAG = "VERSION_TAG";
+
+ /** The xpath to find a project name in an Ant build file. */
+ private static final String XPATH_PROJECT_NAME = "/project/@name";
/** Pattern for characters accepted in a project name. Since this will be used as a
* directory name, we're being a bit conservative on purpose: dot and space cannot be used. */
@@ -225,6 +234,7 @@ public class ProjectCreator {
// files manually.
keywords.put(PH_JAVA_FOLDER, packagePath);
keywords.put(PH_PACKAGE, packageName);
+ keywords.put(PH_VERSION_TAG, Integer.toString(MIN_BUILD_VERSION_TAG));
// compute some activity related information
@@ -456,7 +466,9 @@ public class ProjectCreator {
* <li> Check there's a default.properties with a target *or* --target was specified
* <li> Update default.prop if --target was specified
* <li> Refresh/create "sdk" in local.properties
- * <li> Build.xml: create if not present or no <androidinit(\w|/>) in it
+ * <li> Build.xml: create if not present or if version-tag is found or not. version-tag:custom
+ * prevent any overwrite. version-tag:[integer] will override. missing version-tag will query
+ * the dev.
* </ul>
*
* @param folderPath the folder of the project to update. This folder must exist.
@@ -604,17 +616,43 @@ public class ProjectCreator {
File buildXml = new File(projectFolder, SdkConstants.FN_BUILD_XML);
boolean needsBuildXml = projectName != null || !buildXml.exists();
+ // if it seems there's no need for a new build.xml, look for inside the file
+ // to try to detect old ones that may need updating.
if (!needsBuildXml) {
// we are looking for version-tag: followed by either an integer or "custom".
- if (checkFileContainsRegexp(buildXml, "version-tag:\\s*custom")) { //$NON-NLS-1$
- println("File %1$s is custom and will not be overriden.",
+ if (checkFileContainsRegexp(buildXml, "version-tag:\\s*custom") != null) { //$NON-NLS-1$
+ println("%1$s: Found version-tag: custom. File will not be updated.",
SdkConstants.FN_BUILD_XML);
} else {
- // TODO: look for the version value and update if too old.
- if (!checkFileContainsRegexp(buildXml, "version-tag:\\s*(\\d*)")) { //$NON-NLS-1$
- needsBuildXml = true;
- println("File %1$s is too old and needs to be updated.",
+ Matcher m = checkFileContainsRegexp(buildXml, "version-tag:\\s*(\\d+)"); //$NON-NLS-1$
+ if (m == null) {
+ println("----------\n" +
+ "%1$s: Failed to find version-tag string. File must be updated.\n" +
+ "In order to not erase potential customizations, the file will not be automatically regenerated.\n" +
+ "If no changes have been made to the file, delete it manually and run the command again.\n" +
+ "If you have made customizations to the build process, the file must be manually updated.\n" +
+ "It is recommended to:\n" +
+ "\t* Copy current file to a safe location.\n" +
+ "\t* Delete original file.\n" +
+ "\t* Run command again to generate a new file.\n" +
+ "\t* Port customizations to the new file, by looking at the new rules file\n" +
+ "\t located at <SDK>/tools/ant/build.xml\n" +
+ "\t* Update file to contain\n" +
+ "\t version-tag: custom\n" +
+ "\t to prevent file from being rewritten automatically by the SDK tools.\n" +
+ "----------\n",
SdkConstants.FN_BUILD_XML);
+ } else {
+ String versionStr = m.group(1);
+ if (versionStr != null) {
+ // can't fail due to regexp above.
+ int version = Integer.parseInt(versionStr);
+ if (version < MIN_BUILD_VERSION_TAG) {
+ println("%1$s: Found version-tag: %2$d. Expected version-tag: %3$d: file must be updated.",
+ SdkConstants.FN_BUILD_XML, version, MIN_BUILD_VERSION_TAG);
+ needsBuildXml = true;
+ }
+ }
}
}
}
@@ -623,29 +661,68 @@ public class ProjectCreator {
// create the map for place-holders of values to replace in the templates
final HashMap<String, String> keywords = new HashMap<String, String>();
- // Take the project name from the command line if there's one
- if (projectName != null) {
- keywords.put(PH_PROJECT_NAME, projectName);
- } else {
- extractPackageFromManifest(androidManifest, keywords);
- if (keywords.containsKey(PH_ACTIVITY_ENTRY_NAME)) {
- String activity = keywords.get(PH_ACTIVITY_ENTRY_NAME);
- // keep only the last segment if applicable
- int pos = activity.lastIndexOf('.');
- if (pos != -1) {
- activity = activity.substring(pos + 1);
+ // put the current version-tag value
+ keywords.put(PH_VERSION_TAG, Integer.toString(MIN_BUILD_VERSION_TAG));
+
+ // if there was no project name on the command line, figure one out.
+ if (projectName == null) {
+ // otherwise, take it from the existing build.xml if it exists already.
+ if (buildXml.exists()) {
+ try {
+ XPathFactory factory = XPathFactory.newInstance();
+ XPath xpath = factory.newXPath();
+
+ projectName = xpath.evaluate(XPATH_PROJECT_NAME,
+ new InputSource(new FileInputStream(buildXml)));
+ } catch (XPathExpressionException e) {
+ // this is ok since we're going to recreate the file.
+ mLog.error(e, "Unable to find existing project name from %1$s",
+ SdkConstants.FN_BUILD_XML);
+ } catch (FileNotFoundException e) {
+ // can't happen since we check above.
}
+ }
- // Use the activity as project name
- keywords.put(PH_PROJECT_NAME, activity);
- } else {
- // We need a project name. Just pick up the basename of the project
- // directory.
- projectName = projectFolder.getName();
- keywords.put(PH_PROJECT_NAME, projectName);
+ // if the project is still null, then we find another way.
+ if (projectName == null) {
+ extractPackageFromManifest(androidManifest, keywords);
+ if (keywords.containsKey(PH_ACTIVITY_ENTRY_NAME)) {
+ String activity = keywords.get(PH_ACTIVITY_ENTRY_NAME);
+ // keep only the last segment if applicable
+ int pos = activity.lastIndexOf('.');
+ if (pos != -1) {
+ activity = activity.substring(pos + 1);
+ }
+
+ // Use the activity as project name
+ projectName = activity;
+
+ println("No project name specified, using Activity name '%1$s'.\n" +
+ "If you wish to change it, edit the first line of %2$s.",
+ activity, SdkConstants.FN_BUILD_XML);
+ } else {
+ // We need a project name. Just pick up the basename of the project
+ // directory.
+ File projectCanonicalFolder = projectFolder;
+ try {
+ projectCanonicalFolder = projectCanonicalFolder.getCanonicalFile();
+ } catch (IOException e) {
+ // ignore, keep going
+ }
+
+ // Use the folder name as project name
+ projectName = projectCanonicalFolder.getName();
+
+ println("No project name specified, using project folder name '%1$s'.\n" +
+ "If you wish to change it, edit the first line of %2$s.",
+ projectName, SdkConstants.FN_BUILD_XML);
+ }
}
}
+ // put the project name in the map for replacement during the template installation.
+ keywords.put(PH_PROJECT_NAME, projectName);
+
if (mLevel == OutputLevel.VERBOSE) {
println("Regenerating %1$s with project name %2$s",
SdkConstants.FN_BUILD_XML,
@@ -653,9 +730,7 @@ public class ProjectCreator {
}
try {
- installTemplate("build.template",
- new File(projectFolder, SdkConstants.FN_BUILD_XML),
- keywords);
+ installTemplate("build.template", buildXml, keywords);
} catch (ProjectCreateException e) {
mLog.error(e, null);
return false;
@@ -731,38 +806,35 @@ public class ProjectCreator {
return;
}
- // look for the name of the project. If build.xml does not exist,
- // query the main project build.xml for its name
+ // update test-project does not support the --name parameter, therefore the project
+ // name should generally not be passed to updateProject().
+ // However if build.xml does not exist then updateProject() will recreate it. In this
+ // case we will need the project name.
+ // To do this, we look for the parent project name and add "test" to it.
+ // If the main project does not have a project name (yet), then the default behavior
+ // will be used (look for activity and then folder name)
String projectName = null;
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
- File testBuildXml = new File(folderPath, "build.xml");
- if (testBuildXml.isFile()) {
- try {
- projectName = xpath.evaluate("/project/@name",
- new InputSource(new FileInputStream(testBuildXml)));
- } catch (XPathExpressionException e) {
- // looks like the build.xml is wrong, we'll create a new one, and get its name
- // from the parent.
- } catch (FileNotFoundException e) {
- // looks like the build.xml is wrong, we'll create a new one, and get its name
- // from the parent.
- }
- }
-
- // if the project name is still unknown, get it from the parent.
- if (projectName == null) {
- try {
- String mainProjectName = xpath.evaluate("/project/@name",
- new InputSource(new FileInputStream(new File(resolvedPath, "build.xml"))));
- projectName = mainProjectName + "Test";
- } catch (XPathExpressionException e) {
- mLog.error(e, "Unable to query main project name.");
- return;
- } catch (FileNotFoundException e) {
- mLog.error(e, "Unable to query main project name.");
- return;
+ File testBuildXml = new File(folderPath, SdkConstants.FN_BUILD_XML);
+ if (testBuildXml.isFile() == false) {
+ File mainBuildXml = new File(resolvedPath, SdkConstants.FN_BUILD_XML);
+ if (mainBuildXml.isFile()) {
+ try {
+ // get the name of the main project and add Test to it.
+ String mainProjectName = xpath.evaluate(XPATH_PROJECT_NAME,
+ new InputSource(new FileInputStream(mainBuildXml)));
+ projectName = mainProjectName + "Test";
+ } catch (XPathExpressionException e) {
+ // it's ok, updateProject() will figure out a name automatically.
+ // We do log the error though as the build.xml file may be broken.
+ mLog.warning("Failed to parse %1$s.\n" +
+ "File may not be valid. Consider running 'android update project' on the main project.",
+ mainBuildXml.getPath());
+ } catch (FileNotFoundException e) {
+ // should not happen since we check first.
+ }
}
}
@@ -911,9 +983,15 @@ public class ProjectCreator {
}
/**
- * Returns true if any line of the input file contains the requested regexp.
+ * Looks for a given regex in a file and returns the matcher if any line of the input file
+ * contains the requested regexp.
+ *
+ * @param file the file to search.
+ * @param regexp the regexp to search for.
+ *
+ * @return a Matcher or null if the regexp is not found.
*/
- private boolean checkFileContainsRegexp(File file, String regexp) {
+ private Matcher checkFileContainsRegexp(File file, String regexp) {
Pattern p = Pattern.compile(regexp);
try {
@@ -921,8 +999,9 @@ public class ProjectCreator {
String line;
while ((line = in.readLine()) != null) {
- if (p.matcher(line).find()) {
- return true;
+ Matcher m = p.matcher(line);
+ if (m.find()) {
+ return m;
}
}
@@ -931,7 +1010,7 @@ public class ProjectCreator {
// ignore
}
- return false;
+ return null;
}
/**