Add owner_path(-Path) predicate.

gerrit:commit_delta was too slow for large patch lists. owner_path only
provides the paths to the necessary OWNERS files which makes the check
significantly faster.
diff --git a/CHANGELOG b/CHANGELOG
index 29cefb3..8d6d1b3 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+1.2 - ???
+=====================
+
+* Add owner_path(-Path) to use instead of gerrit:commit_delta
+* Change owner(-Path, _) to bind to the OWNERS file(s) path instead of patch list paths
+
 1.1 - April 29, 2013
 =====================
 
diff --git a/gerrit-owners-common/src/main/java/com/vmware/gerrit/owners/common/PathOwners.java b/gerrit-owners-common/src/main/java/com/vmware/gerrit/owners/common/PathOwners.java
index 1eda4d4..37f6207 100644
--- a/gerrit-owners-common/src/main/java/com/vmware/gerrit/owners/common/PathOwners.java
+++ b/gerrit-owners-common/src/main/java/com/vmware/gerrit/owners/common/PathOwners.java
@@ -109,7 +109,10 @@
         }
       }
 
-      result.putAll(path, currentEntry.getOwners());
+      // Only add the path to the OWNERS file to reduce the number of entries in the result
+      if (currentEntry.getOwnersPath() != null) {
+        result.putAll(currentEntry.getOwnersPath(), currentEntry.getOwners());
+      }
     }
 
     return result;
diff --git a/gerrit-owners/src/main/java/gerrit_owners/PRED_owner_path_1.java b/gerrit-owners/src/main/java/gerrit_owners/PRED_owner_path_1.java
new file mode 100644
index 0000000..e378fcd
--- /dev/null
+++ b/gerrit-owners/src/main/java/gerrit_owners/PRED_owner_path_1.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 VMware, Inc. All Rights Reserved.
+ */
+package gerrit_owners;
+
+import com.vmware.gerrit.owners.OwnersStoredValues;
+import com.vmware.gerrit.owners.common.PathOwners;
+
+import com.googlecode.prolog_cafe.lang.JavaObjectTerm;
+import com.googlecode.prolog_cafe.lang.Operation;
+import com.googlecode.prolog_cafe.lang.Predicate;
+import com.googlecode.prolog_cafe.lang.Prolog;
+import com.googlecode.prolog_cafe.lang.PrologException;
+import com.googlecode.prolog_cafe.lang.SymbolTerm;
+import com.googlecode.prolog_cafe.lang.Term;
+
+import java.util.Iterator;
+
+/**
+ * 'owner_path'(-Path)
+ */
+public class PRED_owner_path_1 extends Predicate.P1 {
+
+  private static final PRED_owner_path_check OWNER_PATH_CHECK = new PRED_owner_path_check();
+  private static final PRED_owner_path_empty OWNER_PATH_EMPTY = new PRED_owner_path_empty();
+  private static final PRED_owner_path_next OWNER_PATH_NEXT = new PRED_owner_path_next();
+
+  public PRED_owner_path_1(Term a1, Operation n) {
+    this.arg1 = a1;
+    this.cont = n;
+  }
+
+  @Override
+  public Operation exec(Prolog engine) throws PrologException {
+    engine.cont = cont;
+    engine.setB0();
+
+    PathOwners owners = OwnersStoredValues.PATH_OWNERS.get(engine);
+    engine.areg1 = arg1;
+    engine.areg2 = new JavaObjectTerm(owners.get().keys().iterator());
+    return engine.jtry2(OWNER_PATH_CHECK, OWNER_PATH_NEXT);
+  }
+
+  private static class PRED_owner_path_check extends Operation {
+
+    @Override
+    public Operation exec(Prolog engine) throws PrologException {
+      Term a1 = engine.areg1;
+      Term a2 = engine.areg2;
+
+      @SuppressWarnings("unchecked")
+      Iterator<String> iter = (Iterator<String>) ((JavaObjectTerm) a2).object();
+      while (iter.hasNext()) {
+        String path = iter.next();
+
+        SymbolTerm pathTerm = SymbolTerm.create(path);
+        if (!a1.unify(pathTerm, engine.trail)) {
+          continue;
+        }
+
+        return engine.cont;
+      }
+      return engine.fail();
+    }
+  }
+
+  private static class PRED_owner_path_next extends Operation {
+
+    @Override
+    public Operation exec(Prolog engine) throws PrologException {
+      return engine.trust(OWNER_PATH_EMPTY);
+    }
+  }
+
+  private static class PRED_owner_path_empty extends Operation {
+
+    @Override
+    public Operation exec(Prolog engine) throws PrologException {
+      Term a2 = engine.areg2;
+
+      @SuppressWarnings("unchecked")
+      Iterator<String> iter = (Iterator<String>) ((JavaObjectTerm) a2).object();
+      if (!iter.hasNext()) {
+        return engine.fail();
+      }
+
+      return engine.jtry2(OWNER_PATH_CHECK, OWNER_PATH_NEXT);
+    }
+  }
+
+}
diff --git a/gerrit-owners/src/main/prolog/gerrit_owners.pl b/gerrit-owners/src/main/prolog/gerrit_owners.pl
index f4ab772..5d54dc4 100644
--- a/gerrit-owners/src/main/prolog/gerrit_owners.pl
+++ b/gerrit-owners/src/main/prolog/gerrit_owners.pl
@@ -5,26 +5,16 @@
 :- public add_owner_approval/3.
 
 add_owner_approval(In, Out) :-
-  gerrit:commit_delta('.*', Type, Path, OldPath),
-  ( Type == 'rename',
-    owner(OldPath, _),
-    \+ owner_approved(OldPath);
-    owner(Path, _),
-    \+ owner_approved(Path)
-  ),
+  owner_path(Path),
+  \+ owner_approved(Path),
   Out = [label('Owner-Approval', need(_)) | In],
   !.
 
 add_owner_approval(In, Out) :- In = Out.
 
 add_owner_approval(Users, In, Out) :-
-  gerrit:commit_delta('.*' ,Type, Path, OldPath),
-  ( Type == 'rename',
-    owner(OldPath, _),
-    \+ owner_approved(Users, OldPath);
-    owner(Path, _),
-    \+ owner_approved(Users, Path)
-  ),
+  owner_path(Path),
+  \+ owner_approved(Users, Path),
   Out = [label('Owner-Approval', need(_)) | In],
   !.