Skip to content

Commit

Permalink
Added incremental java program (see tools/README)
Browse files Browse the repository at this point in the history
  • Loading branch information
elegos committed Jan 25, 2011
1 parent 218a87c commit 18cecd2
Show file tree
Hide file tree
Showing 7 changed files with 367 additions and 1 deletion.
28 changes: 27 additions & 1 deletion tools/README
@@ -1,6 +1,9 @@
This folder contains tools created to make your (ROM maintainer) life easier :)

incremental.php:



-- incremental.php:
this file can be executed in terminal by BASH users (like OSX or Linux)
just make sure to add executive permissions to the files, if needed.

Expand All @@ -16,3 +19,26 @@ incremental.php:
contain errors or useless code (up to you). If not specified, it will only
list the removed, new and changed files.
-h: a list of available arguments




-- incremental.jar
it's just the same of incremental.php, but written in java (may be easier to use for someone).
it has some cool extra options. Source code included in java_incremental_src.
Here is reported the help command:

EleGoS ROM incremental creator
Usage: (option=value or option)
-h, --help print this help
-o previous (old) version directory
-n new version directory
-i (optional) incremental version directory
it must not exist (default: incremental).
-w (optional, no value) write the incremental folder (useless if -i is set)
--app2sd (optional, no value) enables app2sd in the updater-script
--sdType (optional) type of the app2sd partition (default: ext3)
--sdMountPoint (optional) mount point of the app2sd partition (default: /system/sd)
--sdBlock (optional) app2sd partition block (default: mmcblk0p2)

example: java -jar incremental.jar -o=OLD_DIR -n=NEW_DIR -i=MyIncrementalFolder --app2sd --sdType=ext3 --sdMountPoint=/system/sd --sdBlock=mmcblk0p2
Binary file added tools/incremental.jar
Binary file not shown.
6 changes: 6 additions & 0 deletions tools/java_incremental_src/.classpath
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="output" path="bin"/>
</classpath>
17 changes: 17 additions & 0 deletions tools/java_incremental_src/.project
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>incremental</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
57 changes: 57 additions & 0 deletions tools/java_incremental_src/src/incremental/DirChanges.java
@@ -0,0 +1,57 @@
package incremental;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;

public class DirChanges {
private ArrayList<String> newFiles;
private ArrayList<String> modFiles;
private ArrayList<String> rmFiles;

public DirChanges() {
newFiles = new ArrayList<String>();
modFiles = new ArrayList<String>();
rmFiles = new ArrayList<String>();
}

public ArrayList<String> getNewFiles() {
return newFiles;
}

public ArrayList<String> getModifiedFiles() {
return modFiles;
}

public ArrayList<String> getRemovedFiles() {
return rmFiles;
}

public void setLists(Map<String, String> oldMap, Map<String, String> newMap) {
String hash, key;

Iterator<String> theIterator = oldMap.keySet().iterator();
while(theIterator.hasNext()) {
key = theIterator.next();
if(newMap.containsKey(key)) { // file exists in the new version
hash = newMap.get(key);
if(!hash.equals(oldMap.get(key))) // files are different
modFiles.add(key);
}
else // file doesn't exist in the new version
rmFiles.add(key);
}

theIterator = newMap.keySet().iterator();
while(theIterator.hasNext()) {
key = theIterator.next();
if(!oldMap.containsKey(key)) // file doesn't exist in the old version
newFiles.add(key);
}

Collections.sort(newFiles);
Collections.sort(modFiles);
Collections.sort(rmFiles);
}
}
101 changes: 101 additions & 0 deletions tools/java_incremental_src/src/incremental/Main.java
@@ -0,0 +1,101 @@
package incremental;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;

public class Main {
private static String oldROM = "";
private static String newROM = "";
private static String incremental = "";
private static Boolean doWrite = false;
private static Boolean app2sd = false;
private static String sdBlock = "";
private static String sdMountPoint = "";
private static String sdType = "";

public static void main(String[] args) {
System.out.println("EleGoS ROM incremental creator");

int i;
for(i = 0; i < args.length; i++) {
if(args[i].equals("-h") || args[i].equals("--help")) {
printHelp();
return;
}
if(args[i].length() > 3) {
if(args[i].startsWith("-o=")) oldROM = args[i].substring(3);
if(args[i].startsWith("-n=")) newROM = args[i].substring(3);
if(args[i].startsWith("-i=")) {
incremental = args[i].substring(3);
doWrite = true;
}
if(args[i].equals("--app2sd")) app2sd = true;
if(args[i].startsWith("--sdBlock=")) sdBlock = args[i].substring(10);
if(args[i].startsWith("--sdMountPoint=")) sdMountPoint = args[i].substring(15);
if(args[i].startsWith("--sdType=")) sdType = args[i].substring(9);
}
if(args[i].equals("-w")) doWrite = true;
}
if(args.length == 0 || oldROM.equals("") || newROM.equals("")) {
printHelp();
return;
}

Map<String, String> oldMap;
Map<String, String> newMap;
oldMap = SystemIO.loadDirectory(oldROM, oldROM);
newMap = SystemIO.loadDirectory(newROM, newROM);

DirChanges changes = new DirChanges();
changes.setLists(oldMap, newMap);

ArrayList<String> newFiles = changes.getNewFiles();
ArrayList<String> modFiles = changes.getModifiedFiles();
ArrayList<String> rmFiles = changes.getRemovedFiles();

Iterator<String> iter;

System.out.println("New files:");
iter = newFiles.iterator();
while(iter.hasNext())
System.out.println("\t"+iter.next());

System.out.println("Modified files:");
iter = modFiles.iterator();
while(iter.hasNext())
System.out.println("\t"+iter.next());

System.out.println("Removed files:");
iter = rmFiles.iterator();
while(iter.hasNext())
System.out.println("\t"+iter.next());

if(doWrite || !incremental.equals("")) {
if(incremental.equals("")) incremental = "incremental";
newFiles.addAll(modFiles);
newFiles.add("META-INF/com/android/metadata");
newFiles.add("META-INF/com/google/android/update-binary");
System.out.println("Copying files...");
SystemIO.copyFiles(newFiles, incremental, newROM);
System.out.println("Creating updater-script file...");
SystemIO.createUpdaterScript(rmFiles, incremental, app2sd, sdBlock, sdMountPoint, sdType);
System.out.println("Done. Please check the contents before zipping and signing!");
}
}

private static void printHelp() {
System.out.println("Usage: (option=value or option)");
System.out.println("\t-h, --help\tprint this help");
System.out.println("\t-o\t\tprevious (old) version directory");
System.out.println("\t-n\t\tnew version directory");
System.out.println("\t-i\t\t(optional) incremental version directory\n"+
"\t\t\tit must not exist (default: incremental).");
System.out.println("\t-w\t\t(optional, no value) write the incremental folder (useless if -i is set)");
System.out.println("\t--app2sd\t(optional, no value) enables app2sd in the updater-script");
System.out.println("\t--sdType\t(optional) type of the app2sd partition (default: ext3)");
System.out.println("\t--sdMountPoint\t(optional) mount point of the app2sd partition (default: /system/sd)");
System.out.println("\t--sdBlock\t(optional) app2sd partition block (default: mmcblk0p2)");
}

}
159 changes: 159 additions & 0 deletions tools/java_incremental_src/src/incremental/SystemIO.java
@@ -0,0 +1,159 @@
package incremental;

import java.io.*;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class SystemIO {
public static String getMD5Sum(String file) {
MessageDigest md5;
FileInputStream fis;
int read = 0;
byte[] bytes = new byte[1024];
BigInteger bigInt;
String hash = "";

try {
md5 = MessageDigest.getInstance("MD5");
fis = new FileInputStream(file);
while((read = fis.read(bytes)) != -1)
md5.update(bytes, 0, read);
bigInt = new BigInteger(1,md5.digest());
hash = bigInt.toString(16);
while(hash.length() < 32)
hash = "0"+hash;
} catch (Exception e) {
e.printStackTrace();
}

return hash;
}

public static Map<String, String> loadDirectory(String dir, String dir_root) {
Map<String, String> listOfFilesAndMD5 = new HashMap<String, String>();
Map<String, String> recursiveList;
File directory, innerDirectory;
String[] files;
String filePath;
int i;

if(!dir_root.endsWith("/")) dir_root += "/";
if(dir.endsWith("/")) dir = dir.substring(0, dir.length()-1);

directory = new File(dir);
if(directory.isDirectory()) {
files = directory.list();
for(i = 0; i < files.length; i++) {
innerDirectory = new File(dir+"/"+files[i]);
if(innerDirectory.isDirectory()) {
recursiveList = loadDirectory(innerDirectory.toString(),dir_root);
listOfFilesAndMD5.putAll(recursiveList);
} else {
if(files[i].contains("CERT.") ||
files[i].contains("MANIFEST.MF") ||
files[i].contains("updater-script")) continue;
filePath = dir+"/"+files[i];
listOfFilesAndMD5.put(filePath.substring(dir_root.length()), getMD5Sum(dir+"/"+files[i]));
}
}
}


return listOfFilesAndMD5;
}

public static void copyFiles(ArrayList<String> files, String destRoot, String fromRoot) {
if(!destRoot.endsWith("/")) destRoot += "/";
if(!fromRoot.endsWith("/")) fromRoot += "/";

File destDir = new File(destRoot);
if(destDir.exists()) {
System.out.println("Please delete the incremental directory ("+destRoot+") before proceding. Aborted.");
return;
}

if(destDir.mkdirs()) {
Iterator<String> iter = files.iterator();
while(iter.hasNext()) {
String file = iter.next();
String dir = destRoot+file.substring(0,file.lastIndexOf("/"));
File dirFile = new File(dir);
dirFile.mkdirs();

File destFile = new File(destRoot+file);
File fromFile = new File(fromRoot+file);
byte[] buffer = new byte[1024];
int len = 0;

try {
InputStream in = new FileInputStream(fromFile);
OutputStream out = new FileOutputStream(destFile);

while ((len = in.read(buffer)) > 0)
out.write(buffer, 0, len);
in.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
} else System.out.println("It was impossible to create directory "+destRoot);
}

public static void createUpdaterScript(ArrayList<String> rmFiles, String destRoot, Boolean app2sd, String block, String mountPoint, String sdType) {
if(!destRoot.endsWith("/")) destRoot += "/";
File destDir = new File(destRoot+"META-INF/com/google/android/");
destDir.mkdirs();

try {
OutputStream script = new FileOutputStream(destRoot+"META-INF/com/google/android/updater-script");
Iterator<String> iter = rmFiles.iterator();

script.write("ui_print(\"Incremental update - automatically created with the ROM Updater tool\");\n".getBytes());
script.write("mount(\"yaffs2\", \"MTD\", \"system\", \"/system\");\n".getBytes());
script.write("mount(\"yaffs2\", \"MTD\", \"userdata\", \"/data\");\n".getBytes());
if(app2sd) {
if(block.equals("")) block = "mmcblk0p2";
if(mountPoint.equals("")) mountPoint = "/system/sd";
if(sdType.equals("")) sdType = "ext3";
String mount = "mount(\""+sdType+"\", \"MCC\", \"/dev/block/"+block+"\", \""+mountPoint+"\");\n";
script.write(mount.getBytes());
}

script.write("ui_print(\"Deleting old files...\");\n".getBytes());
while(iter.hasNext()) {
String command = "delete(\"/"+iter.next()+"\");\n";
script.write(command.getBytes());
}

File system = new File(destRoot+"system");
if(system.isDirectory()) {
script.write("ui_print(\"Extracting /system files...\");\n".getBytes());
script.write("package_extract_dir(\"system\", \"/system\");\n".getBytes());
}
File data = new File(destRoot+"data");
if(data.isDirectory()) {
script.write("ui_print(\"Extracting /data files...\");\n".getBytes());
script.write("package_extract_dir(\"data\", \"/data\");\n".getBytes());
}
File boot = new File(destRoot+"boot.img");
if(boot.isFile()) {
script.write("ui_print(\"Installing new boot image...\");\n".getBytes());
script.write("assert(package_extract_file(\"boot.img\", \"/tmp/boot.img\"), write_raw_image(\"/tmp/boot.img\", \"boot\"), delete(\"/tmp/boot.img\"));\");\n".getBytes());
}

if(app2sd)
script.write("unmount(\"/system/sd\");\n".getBytes());
script.write("unmount(\"/data\");\n".getBytes());
script.write("unmount(\"/system\");\n".getBytes());

script.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

0 comments on commit 18cecd2

Please sign in to comment.