comparison src/org/tmatesoft/hg/internal/PathScope.java @ 443:072b5f3ed0c8

Path to tell immediate parent-child relationship; more powerful scope impl; tests for both
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 04 May 2012 17:59:22 +0200
parents 1ec6b327a6ac
children
comparison
equal deleted inserted replaced
442:6865eb742883 443:072b5f3ed0c8
1 /* 1 /*
2 * Copyright (c) 2011 TMate Software Ltd 2 * Copyright (c) 2011-2012 TMate Software Ltd
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License. 6 * the Free Software Foundation; version 2 of the License.
7 * 7 *
14 * the terms of a license other than GNU General Public License 14 * the terms of a license other than GNU General Public License
15 * contact TMate Software at support@hg4j.com 15 * contact TMate Software at support@hg4j.com
16 */ 16 */
17 package org.tmatesoft.hg.internal; 17 package org.tmatesoft.hg.internal;
18 18
19 import static org.tmatesoft.hg.util.Path.CompareResult.*;
20
19 import java.util.ArrayList; 21 import java.util.ArrayList;
20 22
23 import org.tmatesoft.hg.util.FileIterator;
21 import org.tmatesoft.hg.util.Path; 24 import org.tmatesoft.hg.util.Path;
25 import org.tmatesoft.hg.util.Path.CompareResult;
22 26
23 /** 27 /**
28 * <ul>
29 * <li> Specify folder to get all files in there included, but no subdirs
30 * <li> Specify folder to get all files and files in subdirectories included
31 * <li> Specify exact set files (with option to accept or not paths leading to them)
32 * </ul>
24 * @author Artem Tikhomirov 33 * @author Artem Tikhomirov
25 * @author TMate Software Ltd. 34 * @author TMate Software Ltd.
26 */ 35 */
27 public class PathScope implements Path.Matcher { 36 public class PathScope implements Path.Matcher {
28 private final Path[] files; 37 private final Path[] files;
29 private final Path[] dirs; 38 private final Path[] dirs;
30 private final boolean recursiveDirs; 39 private final boolean includeNestedDirs;
40 private final boolean includeParentDirs;
41 private final boolean includeDirContent;
42
43 /**
44 * See {@link PathScope#PathScope(boolean, boolean, Path...)}
45 */
46 public PathScope(boolean recursiveDirs, Path... paths) {
47 this(true, recursiveDirs, true, paths);
48 }
31 49
32 public PathScope(boolean recursiveDirs, Path... paths) { 50 /**
51 * With <code>matchParentDirs</code>, <code>recursiveDirs</code> and <code>matchDirContent</code> set to <code>false</code>,
52 * this scope matches only exact paths specified.
53 * <p>
54 * With <code>matchParentDirs</code> set to <code>true</code>, parent directories for files and folders listed in
55 * the <code>paths</code> would get accepted as well (handy for {@link FileIterator FileIterators}).
56 * Note, if supplied path lists a file, parent directory for the file is not matched unless <code>matchParentDirs</code>
57 * is <code>true</code>. To match file's immediate parent without matching all other parents up to the root, just add file parent
58 * along with the file to <code>paths</code>.
59 * <p>
60 * With <code>recursiveDirs</code> set to <code>true</code>, subdirectories (with files) of directories listed in <code>paths</code> would
61 * be matched as well. Similar to `a/b/**`
62 * <p>
63 * With <code>matchDirContent</code> set to <code>true</code>, files right under any directory listed in <code>path</code> would be matched.
64 * Similar to `a/b/*`. Makes little sense to set to <code>false</code> when <code>recursiceDirs</code> is <code>true</code>, although may still
65 * be useful in certain scenarios, e.g. PathScope(false, true, false, "a/") matches files under "a/b/*" and "a/b/c/*", but not files "a/*".
66 *
67 * @param matchParentDirs <code>true</code> to accept parent dirs of supplied paths
68 * @param recursiveDirs <code>true</code> to include subdirectories and files of supplied paths
69 * @param includeDirContent
70 * @param paths files and folders to match
71 */
72 public PathScope(boolean matchParentDirs, boolean recursiveDirs, boolean matchDirContent, Path... paths) {
33 if (paths == null) { 73 if (paths == null) {
34 throw new IllegalArgumentException(); 74 throw new IllegalArgumentException();
35 } 75 }
36 this.recursiveDirs = recursiveDirs; 76 includeParentDirs = matchParentDirs;
77 includeNestedDirs = recursiveDirs;
78 includeDirContent = matchDirContent;
37 ArrayList<Path> f = new ArrayList<Path>(5); 79 ArrayList<Path> f = new ArrayList<Path>(5);
38 ArrayList<Path> d = new ArrayList<Path>(5); 80 ArrayList<Path> d = new ArrayList<Path>(5);
39 for (Path p : paths) { 81 for (Path p : paths) {
40 if (p.isDirectory()) { 82 if (p.isDirectory()) {
41 d.add(p); 83 d.add(p);
47 dirs = d.toArray(new Path[d.size()]); 89 dirs = d.toArray(new Path[d.size()]);
48 } 90 }
49 91
50 public boolean accept(Path path) { 92 public boolean accept(Path path) {
51 if (path.isDirectory()) { 93 if (path.isDirectory()) {
52 // either equals to or parent of a directory we know about. 94 // either equals to or a parent of a directory we know about (i.e. configured dir is *nested* in supplied arg).
53 // If recursiveDirs, accept also if nested to one of our directories. 95 // Also, accept arg if it happened to be nested into configured dir (i.e. one of them is *parent* for the arg),
54 // If one of configured files is nested under the path, accept. 96 // and recursiveDirs is true.
55 for (Path d : dirs) { 97 for (Path d : dirs) {
56 switch(d.compareWith(path)) { 98 switch(d.compareWith(path)) {
57 case Same : return true; 99 case Same : return true;
58 case Nested : return true; 100 case ImmediateChild :
59 case Parent : return recursiveDirs; 101 case Nested : return includeParentDirs; // path is parent to one of our locations
102 case ImmediateParent :
103 case Parent : return includeNestedDirs; // path is nested in one of our locations
60 } 104 }
61 } 105 }
106 if (!includeParentDirs) {
107 return false;
108 }
109 // If one of configured files is nested under the path, and we shall report parents, accept.
110 // Note, I don't respect includeDirContent here as with file it's easy to add parent to paths explicitly, if needed.
111 // (if includeDirContent == .f and includeParentDirs == .f, directory than owns a scope file won't get reported)
62 for (Path f : files) { 112 for (Path f : files) {
63 if (f.compareWith(path) == Path.CompareResult.Nested) { 113 CompareResult cr = f.compareWith(path);
114 if (cr == Nested || cr == ImmediateChild) {
64 return true; 115 return true;
65 } 116 }
66 } 117 }
67 } else { 118 } else {
68 for (Path d : dirs) {
69 if (d.compareWith(path) == Path.CompareResult.Parent) {
70 return true;
71 }
72 }
73 for (Path f : files) { 119 for (Path f : files) {
74 if (f.equals(path)) { 120 if (f.equals(path)) {
75 return true; 121 return true;
76 } 122 }
77 } 123 }
78 // either lives in a directory in out scope 124 // if interested in nested/recursive dirs, shall check if supplied file is under any of our configured locations
79 // or there's a file that matches the path 125 if (!includeNestedDirs && !includeDirContent) {
126 return false;
127 }
128 for (Path d : dirs) {
129 CompareResult cr = d.compareWith(path);
130 if (includeNestedDirs && cr == Parent) {
131 // file is nested in one of our locations
132 return true;
133 }
134 if (includeDirContent && cr == ImmediateParent) {
135 // file is right under one of our directories, and includeDirContents is .t
136 return true;
137 }
138 // try another directory
139 }
80 } 140 }
81 // TODO Auto-generated method stub
82 return false; 141 return false;
83 } 142 }
84 } 143 }