You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ibatis.apache.org by cb...@apache.org on 2008/08/26 05:27:55 UTC

svn commit: r688950 - in /ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration: ./ commands/

Author: cbegin
Date: Mon Aug 25 20:27:54 2008
New Revision: 688950

URL: http://svn.apache.org/viewvc?rev=688950&view=rev
Log:
changed run/undo to up/down respectively
added bootstrap feature
improved status to include pending changes
sql is now parsed for properties

Added:
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/PropertyParser.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/BootstrapCommand.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/DownCommand.java
      - copied, changed from r688273, ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/UndoCommand.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/UpCommand.java
      - copied, changed from r688451, ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/RunCommand.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/template_bootstrap.sql
Removed:
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/RunCommand.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/UndoCommand.java
Modified:
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Change.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/CommandLine.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/MigrationReader.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/BaseCommand.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/InitializeCommand.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/NewCommand.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/StatusCommand.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/VersionCommand.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/template_README

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Change.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Change.java?rev=688950&r1=688949&r2=688950&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Change.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Change.java Mon Aug 25 20:27:54 2008
@@ -2,15 +2,20 @@
 
 import java.math.BigDecimal;
 
-public class Change {
+public class Change implements Comparable {
 
   private BigDecimal id;
   private String description;
   private String appliedTimestamp;
+  private String filename;
 
   public Change() {
   }
 
+  public Change(BigDecimal id) {
+    this.id = id;
+  }
+
   public Change(BigDecimal id, String appliedTimestamp, String description) {
     this.id = id;
     this.appliedTimestamp = appliedTimestamp;
@@ -41,17 +46,34 @@
     this.appliedTimestamp = appliedTimestamp;
   }
 
+  public String getFilename() {
+    return filename;
+  }
+
+  public void setFilename(String filename) {
+    this.filename = filename;
+  }
+
   public String toString() {
-    return id + " " + appliedTimestamp + " " + description;
+    return id + " " + (appliedTimestamp == null ? "pending            " : appliedTimestamp) + " " + description;
+  }
+
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    Change change = (Change) o;
+
+    if (!id.equals(change.id)) return false;
+
+    return true;
+  }
+
+  public int hashCode() {
+    return id.hashCode();
   }
 
-  private String formattedId() {
-    StringBuilder idString = new StringBuilder(id.toString());
-    idString.insert(12,":");
-    idString.insert(10,":");
-    idString.insert(8," ");
-    idString.insert(6,"-");
-    idString.insert(4,"-");
-    return idString.toString();
+  public int compareTo(Object o) {
+    return id.compareTo(((Change)o).getId());
   }
 }

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/CommandLine.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/CommandLine.java?rev=688950&r1=688949&r2=688950&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/CommandLine.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/CommandLine.java Mon Aug 25 20:27:54 2008
@@ -19,14 +19,15 @@
   private static final String HELP = "--help";
 
   private static final String INIT = "init";
+  private static final String BOOTSTRAP = "bootstrap";
   private static final String NEW = "new";
-  private static final String RUN = "run";
+  private static final String UP = "up";
+  private static final String DOWN = "down";
   private static final String VERSION = "version";
-  private static final String UNDO = "undo";
   private static final String STATUS = "status";
 
   private static final Set<String> KNOWN_COMMANDS = Collections.unmodifiableSet(
-      new HashSet<String>(Arrays.asList(INIT, NEW, RUN, VERSION, UNDO, STATUS)));
+      new HashSet<String>(Arrays.asList(INIT, NEW, UP, VERSION, DOWN, STATUS, BOOTSTRAP)));
 
   private File repository;
   private String environment;
@@ -66,16 +67,18 @@
   private void runCommand() {
     if (INIT.equals(command)) {
      new InitializeCommand(repository,environment,force).execute(params);
+    } else if (BOOTSTRAP.equals(command)) {
+      new BootstrapCommand(repository,environment,force).execute(params);
     } else if (NEW.equals(command)) {
       new NewCommand(repository,environment,force).execute(params);
     } else if (STATUS.equals(command)) {
       new StatusCommand(repository,environment,force).execute(params);
-    } else if (RUN.equals(command)) {
-      new RunCommand(repository,environment,force).execute(params);
+    } else if (UP.equals(command)) {
+      new UpCommand(repository,environment,force).execute(params);
     } else if (VERSION.equals(command)) {
       new VersionCommand(repository,environment,force).execute(params);
-    } else if (UNDO.equals(command)) {
-      new UndoCommand(repository,environment,force).execute(params);
+    } else if (DOWN.equals(command)) {
+      new DownCommand(repository,environment,force).execute(params);
     } else {
       throw new RuntimeException("Attempt to execute unkown command.");
     }
@@ -139,9 +142,10 @@
     out.println();
     out.println("Commands:");
     out.println("  init               Creates (if necessary) and initializes a migration path.");
+    out.println("  bootstrap          Runs the bootstrap SQL script (see scripts/bootstrap.sql for more).");
     out.println("  new <description>  Creates a new migration with the provided description.");
-    out.println("  run                Run all unapplied migrations.");
-    out.println("  undo               Undoes the last migration applied to the database.");
+    out.println("  up                 Run all unapplied migrations.");
+    out.println("  down               Undoes the last migration applied to the database.");
     out.println("  version <version>  Migrates the database up or down to the specified version.");
     out.println("  status             Prints the changelog from the database if the changelog table exists.");
     out.println();

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/MigrationReader.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/MigrationReader.java?rev=688950&r1=688949&r2=688950&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/MigrationReader.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/MigrationReader.java Mon Aug 25 20:27:54 2008
@@ -4,12 +4,13 @@
 import java.io.IOException;
 import java.io.BufferedReader;
 import java.io.StringReader;
+import java.util.*;
 
 public class MigrationReader extends Reader {
 
   private Reader target;
 
-  public MigrationReader(Reader source, boolean undo) throws IOException {
+  public MigrationReader(Reader source, boolean undo, Properties variables) throws IOException {
     try {
       BufferedReader reader = new BufferedReader(source);
       StringBuilder doBuilder = new StringBuilder();
@@ -26,9 +27,9 @@
         }
       }
       if (undo) {
-        target = new StringReader(undoBuilder.toString());
+        target = new StringReader(PropertyParser.parse(undoBuilder.toString(),variables));
       } else {
-        target = new StringReader(doBuilder.toString());
+        target = new StringReader(PropertyParser.parse(doBuilder.toString(),variables));
       }
     } finally {
       source.close();

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/PropertyParser.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/PropertyParser.java?rev=688950&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/PropertyParser.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/PropertyParser.java Mon Aug 25 20:27:54 2008
@@ -0,0 +1,33 @@
+package org.apache.ibatis.migration;
+
+import java.util.*;
+
+public class PropertyParser {
+
+  public static String parse(String string, Properties variables) {
+    final String OPEN = "${";
+    final String CLOSE = "}";
+    String newString = string;
+    if (newString != null && variables != null) {
+      int start = newString.indexOf(OPEN);
+      int end = newString.indexOf(CLOSE);
+
+      while (start > -1 && end > start) {
+        String prepend = newString.substring(0, start);
+        String append = newString.substring(end + CLOSE.length());
+        String propName = newString.substring(start + OPEN.length(), end);
+        String propValue = variables.getProperty(propName);
+        if (propValue == null) {
+          newString = prepend + append;
+        } else {
+          newString = prepend + propValue + append;
+        }
+        start = newString.indexOf(OPEN);
+        end = newString.indexOf(CLOSE);
+      }
+    }
+    return newString;
+  }
+
+
+}

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/BaseCommand.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/BaseCommand.java?rev=688950&r1=688949&r2=688950&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/BaseCommand.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/BaseCommand.java Mon Aug 25 20:27:54 2008
@@ -1,8 +1,6 @@
 package org.apache.ibatis.migration.commands;
 
-import org.apache.ibatis.migration.Change;
-import org.apache.ibatis.migration.MigrationException;
-import org.apache.ibatis.migration.ScriptRunner;
+import org.apache.ibatis.migration.*;
 import org.apache.ibatis.adhoc.AdHocExecutor;
 import org.apache.ibatis.io.Resources;
 
@@ -33,34 +31,22 @@
     this.environment = environment;
     this.force = force;
   }
-
-  protected void reverse(Comparable[] comparable) {
-    Arrays.sort(comparable, new Comparator() {
-      public int compare(Object o1, Object o2) {
-        return ((Comparable) o2).compareTo(o1);
-      }
-    });
-  }
   
   protected boolean paramsEmpty(String... params) {
     return params == null || params.length < 1 || params[0] == null || params[0].length() < 1;
   }
 
-  protected Change parseChangeFromFilename(String filename) {
-    try {
-      Change change = new Change();
-      String[] parts = filename.split("\\.")[0].split("_");
-      change.setId(new BigDecimal(parts[0]));
-      StringBuilder builder = new StringBuilder();
-      for (int i = 1; i < parts.length; i++) {
-        if (i > 1) builder.append(" ");
-        builder.append(parts[i]);
+  protected List<Change> getMigrations() {
+    String[] filenames = scriptPath.list();
+    Arrays.sort(filenames);
+    List<Change> migrations = new ArrayList<Change>();
+    for(String filename : filenames) {
+      if (filename.endsWith(".sql") && !"bootstrap.sql".equals(filename)) {
+        Change change = parseChangeFromFilename(filename);
+        migrations.add(change);
       }
-      change.setDescription(builder.toString());
-      return change;
-    } catch (Exception e) {
-      throw new MigrationException("Error parsing change from file.  Cause: " + e, e);
     }
+    return migrations;
   }
 
   protected List<Change> getChangelog() {
@@ -126,7 +112,7 @@
     copyResourceTo(resource, toFile, null);
   }
 
-  protected void copyResourceTo(String resource, File toFile, Map<String, String> variables) {
+  protected void copyResourceTo(String resource, File toFile, Properties variables) {
     out.println("Creating: " + toFile.getName());
     try {
       LineNumberReader reader = new LineNumberReader(Resources.getResourceAsReader(this.getClass().getClassLoader(), resource));
@@ -135,7 +121,7 @@
         try {
           String line;
           while ((line = reader.readLine()) != null) {
-            line = parsePlaceholders(line, variables);
+            line = PropertyParser.parse(line, variables);
             writer.println(line);
           }
         } finally {
@@ -228,11 +214,7 @@
     }
   }
 
-  private File subdirectory(File base, String sub) {
-    return new File(base.getAbsoluteFile() + File.separator + sub);
-  }
-
-  private Properties getEnvironmentProperties() {
+  protected Properties getEnvironmentProperties() {
     try {
       File file = existingEnvironmentFile();
       Properties props = new Properties();
@@ -243,29 +225,26 @@
     }
   }
 
-  private String parsePlaceholders(String string, Map<String, String> variables) {
-    final String OPEN = "${";
-    final String CLOSE = "}";
-    String newString = string;
-    if (newString != null && variables != null) {
-      int start = newString.indexOf(OPEN);
-      int end = newString.indexOf(CLOSE);
-
-      while (start > -1 && end > start) {
-        String prepend = newString.substring(0, start);
-        String append = newString.substring(end + CLOSE.length());
-        String propName = newString.substring(start + OPEN.length(), end);
-        String propValue = variables.get(propName);
-        if (propValue == null) {
-          newString = prepend + append;
-        } else {
-          newString = prepend + propValue + append;
-        }
-        start = newString.indexOf(OPEN);
-        end = newString.indexOf(CLOSE);
+  private File subdirectory(File base, String sub) {
+    return new File(base.getAbsoluteFile() + File.separator + sub);
+  }
+
+  private Change parseChangeFromFilename(String filename) {
+    try {
+      Change change = new Change();
+      String[] parts = filename.split("\\.")[0].split("_");
+      change.setId(new BigDecimal(parts[0]));
+      StringBuilder builder = new StringBuilder();
+      for (int i = 1; i < parts.length; i++) {
+        if (i > 1) builder.append(" ");
+        builder.append(parts[i]);
       }
+      change.setDescription(builder.toString());
+      change.setFilename(filename);
+      return change;
+    } catch (Exception e) {
+      throw new MigrationException("Error parsing change from file.  Cause: " + e, e);
     }
-    return newString;
   }
 
 }

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/BootstrapCommand.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/BootstrapCommand.java?rev=688950&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/BootstrapCommand.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/BootstrapCommand.java Mon Aug 25 20:27:54 2008
@@ -0,0 +1,33 @@
+package org.apache.ibatis.migration.commands;
+
+import org.apache.ibatis.migration.*;
+
+import java.io.*;
+import java.util.Arrays;
+
+public class BootstrapCommand extends BaseCommand {
+
+  public BootstrapCommand(File repository, String environment, boolean force) {
+    super(repository, environment, force);
+  }
+
+  public void execute(String... params) {
+    try {
+      if (changelogExists()) {
+        out.println("For your safety, the bootstrap SQL script will only run before migrations are applied (i.e. before the changelog exists).");
+      } else {
+        File bootstrap = scriptFile("bootstrap.sql");
+        if (bootstrap.exists()) {
+          out.println(horizontalLine("Applying: bootstrap.sql", 80));
+          ScriptRunner runner = getScriptRunner();
+          runner.runScript(new MigrationReader(new FileReader(bootstrap), false, getEnvironmentProperties()));
+        } else {
+          out.println("Error, could not run bootstrap.sql.  The file does not exist.");
+        }
+      }
+    } catch (Exception e) {
+      throw new RuntimeException("<Description>.  Cause: " + e, e);
+    }
+  }
+
+}

Copied: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/DownCommand.java (from r688273, ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/UndoCommand.java)
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/DownCommand.java?p2=ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/DownCommand.java&p1=ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/UndoCommand.java&r1=688273&r2=688950&rev=688950&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/UndoCommand.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/DownCommand.java Mon Aug 25 20:27:54 2008
@@ -8,35 +8,31 @@
 
 import java.io.File;
 import java.io.FileReader;
-import java.util.Arrays;
-import java.util.Comparator;
+import java.util.*;
 import java.sql.SQLException;
 
-public class UndoCommand extends BaseCommand {
+public class DownCommand extends BaseCommand {
 
-  public UndoCommand(File repository, String environment, boolean force) {
+  public DownCommand(File repository, String environment, boolean force) {
     super(repository, environment, force);
   }
 
   public void execute(String... params) {
-    try {
-      String[] filenames = scriptPath.list();
-      reverse(filenames);
+    try {     
       Change lastChange = getLastAppliedChange();
-      for (String filename : filenames) {
-        if (filename.endsWith(".sql")) {
-          Change change = parseChangeFromFilename(filename);
-          if (change.getId().equals(lastChange.getId())) {
-            out.println(horizontalLine("Undoing: " + filename, 80));
-            ScriptRunner runner = getScriptRunner();
-            runner.runScript(new MigrationReader(new FileReader(scriptFile(filename)), true));
-            if (changelogExists()) {
-              deleteChange(change);
-            } else {
-              out.println("Changelog doesn't exist. No further migrations will be undone (normal for the last migration).");
-            }
-            break;
+      List<Change> migrations = getMigrations();
+      Collections.reverse(migrations);
+      for (Change change : migrations) {
+        if (change.getId().equals(lastChange.getId())) {
+          out.println(horizontalLine("Undoing: " + change.getFilename(), 80));
+          ScriptRunner runner = getScriptRunner();
+          runner.runScript(new MigrationReader(new FileReader(scriptFile(change.getFilename())), true, getEnvironmentProperties()));
+          if (changelogExists()) {
+            deleteChange(change);
+          } else {
+            out.println("Changelog doesn't exist. No further migrations will be undone (normal for the last migration).");
           }
+          break;
         }
       }
     } catch (Exception e) {

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/InitializeCommand.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/InitializeCommand.java?rev=688950&r1=688949&r2=688950&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/InitializeCommand.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/InitializeCommand.java Mon Aug 25 20:27:54 2008
@@ -3,7 +3,7 @@
 import org.apache.ibatis.migration.MigrationException;
 
 import java.io.File;
-import java.util.HashMap;
+import java.util.*;
 
 public class InitializeCommand extends BaseCommand {
 
@@ -25,7 +25,7 @@
     copyResourceTo("org/apache/ibatis/migration/template_environment.properties", environmentFile());
     copyResourceTo("org/apache/ibatis/migration/template_changelog.sql", scriptFile(getNextIDAsString() + "_create_changelog.sql"));
     copyResourceTo("org/apache/ibatis/migration/template_migration.sql", scriptFile(getNextIDAsString() + "_first_migration.sql"),
-        new HashMap<String,String>(){{put("description","First migration.");}});
+        new Properties(){{setProperty("description","First migration.");}});
     out.println("Done!");
   }
 

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/NewCommand.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/NewCommand.java?rev=688950&r1=688949&r2=688950&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/NewCommand.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/NewCommand.java Mon Aug 25 20:27:54 2008
@@ -3,8 +3,7 @@
 import org.apache.ibatis.migration.MigrationException;
 
 import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
 
 public class NewCommand extends BaseCommand {
 
@@ -17,8 +16,8 @@
       throw new MigrationException("No description specified for new migration.");
     }
     String description = params[0];
-    Map<String, String> variables = new HashMap<String, String>();
-    variables.put("description", description);
+    Properties variables = new Properties();
+    variables.setProperty("description", description);
     existingEnvironmentFile();
     String filename = getNextIDAsString() + "_" + description.replace(' ', '_') + ".sql";
     copyResourceTo("org/apache/ibatis/migration/template_migration.sql", scriptFile(filename), variables);

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/StatusCommand.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/StatusCommand.java?rev=688950&r1=688949&r2=688950&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/StatusCommand.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/StatusCommand.java Mon Aug 25 20:27:54 2008
@@ -2,7 +2,7 @@
 
 import org.apache.ibatis.migration.Change;
 
-import java.util.List;
+import java.util.*;
 import java.io.File;
 
 public class StatusCommand extends BaseCommand {
@@ -12,16 +12,28 @@
   }
 
   public void execute(String... params) {
+    out.println("ID             Applied At          Description");
+    out.println(horizontalLine("", 60));
+    List<Change> merged = new ArrayList<Change>();
+    List<Change> migrations = getMigrations();
     if (changelogExists()) {
       List<Change> changelog = getChangelog();
-      out.println("ID             Applied At          Description");
-      out.println(horizontalLine("", 60));
-      for (Change change : changelog) {
-        out.println(change);
+      for (Change change : migrations) {
+        int index = changelog.indexOf(change);
+        if (index > -1) {
+          merged.add(changelog.get(index));
+        } else {
+          merged.add(change);
+        }
       }
+      Collections.sort(merged);
     } else {
-      out.println("Changelog does not exist.");
+      merged.addAll(migrations);
+    }
+    for(Change change : merged) {
+      out.println(change);
     }
   }
 
+
 }

Copied: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/UpCommand.java (from r688451, ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/RunCommand.java)
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/UpCommand.java?p2=ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/UpCommand.java&p1=ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/RunCommand.java&r1=688451&r2=688950&rev=688950&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/RunCommand.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/UpCommand.java Mon Aug 25 20:27:54 2008
@@ -8,42 +8,38 @@
 
 import java.io.File;
 import java.io.FileReader;
-import java.util.Arrays;
+import java.util.*;
 import java.sql.SQLException;
 import java.text.SimpleDateFormat;
 
-public class RunCommand extends BaseCommand {
+public class UpCommand extends BaseCommand {
 
   private boolean runOneStepOnly = false;
 
-  public RunCommand(File repository, String environment, boolean force) {
+  public UpCommand(File repository, String environment, boolean force) {
     super(repository,environment,force);
   }
 
-  public RunCommand(File repository, String environment, boolean force, boolean runOneStepOnly) {
+  public UpCommand(File repository, String environment, boolean force, boolean runOneStepOnly) {
     super(repository, environment, force);
     this.runOneStepOnly = runOneStepOnly;
   }
 
   public void execute(String... params) {
     try {
-      String[] filenames = scriptPath.list();
-      Arrays.sort(filenames);
       Change lastChange = null; 
       if (changelogExists()) {
         lastChange = getLastAppliedChange();
       }
-      for (String filename : filenames) {
-        if (filename.endsWith(".sql")) {
-          Change change = parseChangeFromFilename(filename);
-          if (lastChange == null || change.getId().compareTo(lastChange.getId()) > 0) {
-            out.println(horizontalLine("Applying: " + filename, 80));
-            ScriptRunner runner = getScriptRunner();
-            runner.runScript(new MigrationReader(new FileReader(scriptFile(filename)), false));
-            insertChangelog(change);
-            if (runOneStepOnly) {
-              break;
-            }
+      List<Change> migrations = getMigrations();
+      for (Change change : migrations) {
+        if (lastChange == null || change.getId().compareTo(lastChange.getId()) > 0) {
+          out.println(horizontalLine("Applying: " + change.getFilename(), 80));
+          ScriptRunner runner = getScriptRunner();
+          runner.runScript(new MigrationReader(new FileReader(scriptFile(change.getFilename())), false, getEnvironmentProperties()));
+          insertChangelog(change);
+          if (runOneStepOnly) {
+            break;
           }
         }
       }

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/VersionCommand.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/VersionCommand.java?rev=688950&r1=688949&r2=688950&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/VersionCommand.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/commands/VersionCommand.java Mon Aug 25 20:27:54 2008
@@ -4,6 +4,7 @@
 
 import java.io.File;
 import java.math.BigDecimal;
+import java.util.List;
 
 public class VersionCommand extends BaseCommand {
 
@@ -21,16 +22,16 @@
     Change change = getLastAppliedChange();
     if (version.compareTo(change.getId()) > 0) {
       out.println("Upgrading to: " + version);  
-      Command run = new RunCommand(basePath,environment,force,true);
+      Command up = new UpCommand(basePath,environment,force,true);
       while (!version.equals(change.getId())) {
-        run.execute();
+        up.execute();
         change = getLastAppliedChange();
       }
     } else if (version.compareTo(change.getId()) < 0) {
       out.println("Downgrading to: " + version);
-      Command undo = new UndoCommand(basePath,environment,force);
+      Command down = new DownCommand(basePath,environment,force);
       while (!version.equals(change.getId())) {
-        undo.execute();
+        down.execute();
         change = getLastAppliedChange();
       }
     } else {
@@ -53,17 +54,8 @@
   }
 
   private void ensureVersionExists(String... params) {
-    String[] filenames = scriptPath.list();
-    reverse(filenames);
-    boolean found = false;
-    String prefix = params[0] + "_";
-    for (String filename : filenames) {
-      if (filename.startsWith(prefix)) {
-        found = true;
-        break;
-      }
-    }
-    if (!found) {
+    List<Change> migrations = getMigrations();
+    if (!migrations.contains(new Change(new BigDecimal(params[0])))) {
       throw new MigrationException("A migration for the specified version number does not exist.");
     }
   }

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/template_README
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/template_README?rev=688950&r1=688949&r2=688950&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/template_README (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/template_README Mon Aug 25 20:27:54 2008
@@ -29,8 +29,8 @@
 structure.  By default, the directory will contain the script to
 create the changelog table, plus one empty "first" migration script.
 To create a new migration script, use the "new" command.  To run
-all pending migrations, use the "run" command.  To undo the last
-migration applied, use the "undo" command etc.
+all pending migrations, use the "up" command.  To undo the last
+migration applied, use the "down" command etc.
 
 For more information about commands and options, run the ibatis
 migration script with the --help option.

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/template_bootstrap.sql
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/template_bootstrap.sql?rev=688950&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/template_bootstrap.sql (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/template_bootstrap.sql Mon Aug 25 20:27:54 2008
@@ -0,0 +1,36 @@
+--// Bootstrap.sql
+
+-- This is the only SQL script file that is NOT
+-- a valid migration and will not be run or tracked
+-- in the changelog.  There is no @UNDO section.
+
+--// Do I need this file?
+
+-- New projects likely won't need this file.
+-- Existing projects will likely need this file.
+-- It's unlikely that this bootstrap should be run
+-- in the production environment.
+
+--// Purpose
+
+-- The purpose of this file is to provide a facility
+-- to initialize the database to a state before iBATIS
+-- SQL migrations were applied.  If you already have
+-- a database in production, then you probably have
+-- a script that you run on your developer machine
+-- to initialize the database.  That script can now
+-- be put in this bootstrap file (but does not have
+-- to be if you are comfortable with your current process.
+
+--// Running
+
+-- The bootstrap SQL is run with the "migrate bootstrap"
+-- command.  It must be run manually, it's never run as
+-- part of the regular migration process and will never
+-- be undone. Variables (e.g. ${variable}) are still
+-- parsed in the bootstrap SQL.
+
+-- After the boostrap SQL has been run, you can then
+-- use the migrations and the changelog for all future
+-- database change management.
+