annotate src/org/tmatesoft/hg/internal/PathGlobMatcher.java @ 254:a620f0663a37

Collect tags for a file - improve performance of 'sparse' manifest reads
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Tue, 16 Aug 2011 04:03:29 +0200
parents 1ec6b327a6ac
children 981f9f50bb6c
rev   line source
114
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
1 /*
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
2 * Copyright (c) 2011 TMate Software Ltd
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
3 *
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
4 * This program is free software; you can redistribute it and/or modify
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
5 * it under the terms of the GNU General Public License as published by
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
6 * the Free Software Foundation; version 2 of the License.
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
7 *
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
8 * This program is distributed in the hope that it will be useful,
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
11 * GNU General Public License for more details.
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
12 *
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
13 * For information on how to redistribute this software under
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
14 * the terms of a license other than GNU General Public License
130
7567f4a42fe5 Correct contact address
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 118
diff changeset
15 * contact TMate Software at support@hg4j.com
114
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
16 */
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
17 package org.tmatesoft.hg.internal;
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
18
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
19 import java.util.regex.PatternSyntaxException;
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
20
133
4a948ec83980 core.Path to util.Path as it's not Hg repo dependant
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 130
diff changeset
21 import org.tmatesoft.hg.util.Path;
114
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
22
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
23 /**
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
24 *
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
25 * @author Artem Tikhomirov
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
26 * @author TMate Software Ltd.
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
27 */
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
28 public class PathGlobMatcher implements Path.Matcher {
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
29
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
30 private final PathRegexpMatcher delegate;
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
31
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
32 /**
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
33 *
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
34 * @param globPatterns
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
35 * @throws NullPointerException if argument is null
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
36 * @throws IllegalArgumentException if any of the patterns is not valid
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
37 */
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
38 public PathGlobMatcher(String... globPatterns) {
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
39 String[] regexp = new String[globPatterns.length]; //deliberately let fail with NPE
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
40 int i = 0;
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
41 for (String s : globPatterns) {
229
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
42 regexp[i++] = glob2regexp(s);
114
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
43 }
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
44 try {
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
45 delegate = new PathRegexpMatcher(regexp);
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
46 } catch (PatternSyntaxException ex) {
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
47 ex.printStackTrace();
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
48 throw new IllegalArgumentException(ex);
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
49 }
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
50 }
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
51
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
52
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
53 // HgIgnore.glob2regex is similar, but IsIgnore solves slightly different task
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
54 // (need to match partial paths, e.g. for glob 'bin' shall match not only 'bin' folder, but also any path below it,
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
55 // which is not generally the case
229
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
56 private static String glob2regexp(String glob) { // FIXME TESTS NEEDED!!!
114
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
57 int end = glob.length() - 1;
229
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
58 if (glob.length() > 2 && glob.charAt(end) == '*' && glob.charAt(end - 1) == '.') {
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
59 end-=2;
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
60 }
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
61 boolean needLineEndMatch = true;//glob.charAt(end) != '*';
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
62 // while (end > 0 && glob.charAt(end) == '*') end--; // remove trailing * that are useless for Pattern.find()
114
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
63 StringBuilder sb = new StringBuilder(end*2);
229
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
64 // if (glob.charAt(0) != '*') {
118
68ba22a2133a Defects in the filter initialization
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 114
diff changeset
65 sb.append('^');
229
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
66 // }
114
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
67 for (int i = 0; i <= end; i++) {
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
68 char ch = glob.charAt(i);
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
69 if (ch == '*') {
229
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
70 if (i < end && glob.charAt(i+1) == '*') {
114
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
71 // any char, including path segment separator
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
72 sb.append(".*?");
118
68ba22a2133a Defects in the filter initialization
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 114
diff changeset
73 i++;
229
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
74 if (i < end && glob.charAt(i+1) == '/') {
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
75 sb.append("/?");
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
76 i++;
1ec6b327a6ac Scope for status reworked: explicit files or a general matcher
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 133
diff changeset
77 }
114
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
78 } else {
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
79 // just path segments
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
80 sb.append("[^/]*?");
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
81 }
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
82 continue;
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
83 } else if (ch == '?') {
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
84 sb.append("[^/]");
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
85 continue;
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
86 } else if (ch == '.' || ch == '\\') {
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
87 sb.append('\\');
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
88 }
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
89 sb.append(ch);
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
90 }
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
91 if (needLineEndMatch) {
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
92 sb.append('$');
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
93 }
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
94 return sb.toString();
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
95 }
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
96
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
97 public boolean accept(Path path) {
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
98 return delegate.accept(path);
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
99 }
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
100
46291ec605a0 Filters to read and initialize according to configuration files
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
101 }