annotate src/org/tmatesoft/hg/internal/StoragePathHelper.java @ 338:3cfa4d908fc9

Add options to control DataAccessProvider, allow to turn off use of file memory mapping in particular to solve potential sharing violation (os file handle gets released on MappedByteByffer being GC'd, not on FileChannel.close())
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Tue, 15 Nov 2011 04:47:03 +0100
parents a415fe296a50
children 6d2c6b2469fc
rev   line source
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
1 /*
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
2 * Copyright (c) 2011 TMate Software Ltd
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
3 *
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
4 * This program is free software; you can redistribute it and/or modify
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
5 * it under the terms of the GNU General Public License as published by
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
6 * the Free Software Foundation; version 2 of the License.
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
7 *
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
8 * This program is distributed in the hope that it will be useful,
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
11 * GNU General Public License for more details.
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
12 *
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
13 * For information on how to redistribute this software under
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
14 * the terms of a license other than GNU General Public License
102
a3a2e5deb320 Updated contact address to support@hg4j.com
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 83
diff changeset
15 * contact TMate Software at support@hg4j.com
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
16 */
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
17 package org.tmatesoft.hg.internal;
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
18
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
19 import java.util.Arrays;
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
20 import java.util.TreeSet;
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
21
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
22 import org.tmatesoft.hg.util.PathRewrite;
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
23
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
24 /**
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
25 * @see http://mercurial.selenic.com/wiki/CaseFoldingPlan
80
4222b04f34ee Follow history of a file
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 74
diff changeset
26 * @see http://mercurial.selenic.com/wiki/fncacheRepoFormat
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
27 *
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
28 * @author Artem Tikhomirov
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
29 * @author TMate Software Ltd.
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
30 */
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
31 class StoragePathHelper implements PathRewrite {
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
32
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
33 private final boolean store;
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
34 private final boolean fncache;
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
35 private final boolean dotencode;
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
36
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
37 public StoragePathHelper(boolean isStore, boolean isFncache, boolean isDotencode) {
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
38 store = isStore;
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
39 fncache = isFncache;
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
40 dotencode = isDotencode;
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
41 }
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
42
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
43 // FIXME document what path argument is, whether it includes .i or .d, and whether it's 'normalized' (slashes) or not.
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
44 // since .hg/store keeps both .i files and files without extension (e.g. fncache), guees, for data == false
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
45 // we shall assume path has extension
292
a415fe296a50 Refactor PathRewrite to accept any char sequence, not only string
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 138
diff changeset
46 public CharSequence rewrite(CharSequence p) {
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
47 final String STR_STORE = "store/";
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
48 final String STR_DATA = "data/";
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
49 final String STR_DH = "dh/";
83
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
50 final String reservedChars = "\\:*?\"<>|";
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
51 char[] hexByte = new char[2];
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
52
292
a415fe296a50 Refactor PathRewrite to accept any char sequence, not only string
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 138
diff changeset
53 String path = p.toString();
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
54 path = path.replace(".hg/", ".hg.hg/").replace(".i/", ".i.hg/").replace(".d/", ".d.hg/");
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
55 StringBuilder sb = new StringBuilder(path.length() << 1);
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
56 if (store || fncache) {
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
57 // encodefilename
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
58 for (int i = 0; i < path.length(); i++) {
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
59 final char ch = path.charAt(i);
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
60 if (ch >= 'a' && ch <= 'z') {
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
61 sb.append(ch); // POIRAE
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
62 } else if (ch >= 'A' && ch <= 'Z') {
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
63 sb.append('_');
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
64 sb.append(Character.toLowerCase(ch)); // Perhaps, (char) (((int) ch) + 32)? Even better, |= 0x20?
83
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
65 } else if (reservedChars.indexOf(ch) != -1) {
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
66 sb.append('~');
83
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
67 sb.append(toHexByte(ch, hexByte));
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
68 } else if ((ch >= '~' /*126*/ && ch <= 255) || ch < ' ' /*32*/) {
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
69 sb.append('~');
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
70 sb.append(toHexByte(ch, hexByte));
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
71 } else if (ch == '_') {
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
72 sb.append('_');
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
73 sb.append('_');
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
74 } else {
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
75 sb.append(ch);
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
76 }
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
77 }
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
78 // auxencode
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
79 if (fncache) {
83
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
80 encodeWindowsDeviceNames(sb);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
81 }
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
82 }
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
83 final int MAX_PATH_LEN = 120;
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
84 if (fncache && (sb.length() + STR_DATA.length() + ".i".length() > MAX_PATH_LEN)) {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
85 String digest = new DigestHelper().sha1(STR_DATA, path, ".i").asHexString();
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
86 final int DIR_PREFIX_LEN = 8;
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
87 // not sure why (-4) is here. 120 - 40 = up to 80 for path with ext. dh/ + ext(.i) = 3+2
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
88 final int MAX_DIR_PREFIX = 8 * (DIR_PREFIX_LEN + 1) - 4;
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
89 sb = new StringBuilder(MAX_PATH_LEN);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
90 for (int i = 0; i < path.length(); i++) {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
91 final char ch = path.charAt(i);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
92 if (ch >= 'a' && ch <= 'z') {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
93 sb.append(ch);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
94 } else if (ch >= 'A' && ch <= 'Z') {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
95 sb.append((char) (ch | 0x20)); // lowercase
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
96 } else if (reservedChars.indexOf(ch) != -1) {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
97 sb.append('~');
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
98 sb.append(toHexByte(ch, hexByte));
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
99 } else if ((ch >= '~' /*126*/ && ch <= 255) || ch < ' ' /*32*/) {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
100 sb.append('~');
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
101 sb.append(toHexByte(ch, hexByte));
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
102 } else {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
103 sb.append(ch);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
104 }
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
105 }
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
106 encodeWindowsDeviceNames(sb);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
107 int fnameStart = sb.lastIndexOf("/"); // since we rewrite file names, it never ends with slash (for dirs, I'd pass length-2);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
108 StringBuilder completeHashName = new StringBuilder(MAX_PATH_LEN);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
109 completeHashName.append(STR_STORE);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
110 completeHashName.append(STR_DH);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
111 if (fnameStart == -1) {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
112 // no dirs, just long filename
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
113 sb.setLength(MAX_PATH_LEN - 40 /*digest.length()*/ - STR_DH.length() - ".i".length());
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
114 completeHashName.append(sb);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
115 } else {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
116 StringBuilder sb2 = new StringBuilder(MAX_PATH_LEN);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
117 int x = 0;
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
118 do {
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
119 int i = sb.indexOf("/", x);
83
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
120 final int sb2Len = sb2.length();
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
121 if (i-x <= DIR_PREFIX_LEN) { // a b c d e f g h /
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
122 sb2.append(sb, x, i + 1); // with slash
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
123 } else {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
124 sb2.append(sb, x, x + DIR_PREFIX_LEN);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
125 // may unexpectedly end with bad character
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
126 final int last = sb2.length()-1;
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
127 char lastChar = sb2.charAt(last);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
128 assert lastChar == sb.charAt(x + DIR_PREFIX_LEN - 1);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
129 if (lastChar == '.' || lastChar == ' ') {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
130 sb2.setCharAt(last, '_');
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
131 }
83
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
132 sb2.append('/');
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
133 }
83
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
134 if (sb2.length()-1 > MAX_DIR_PREFIX) {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
135 sb2.setLength(sb2Len); // strip off last segment, it's too much
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
136 break;
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
137 }
83
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
138 x = i+1;
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
139 } while (x < fnameStart);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
140 assert sb2.charAt(sb2.length() - 1) == '/';
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
141 int left = MAX_PATH_LEN - sb2.length() - 40 /*digest.length()*/ - STR_DH.length() - ".i".length();
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
142 assert left >= 0;
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
143 fnameStart++; // move from / to actual name
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
144 sb2.append(sb, fnameStart, fnameStart + left > sb.length() ? sb.length() : fnameStart+left);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
145 completeHashName.append(sb2);
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
146 }
83
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
147 completeHashName.append(digest);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
148 sb = completeHashName;
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
149 } else if (store) {
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
150 sb.insert(0, STR_STORE + STR_DATA);
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
151 }
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
152 sb.append(".i");
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
153 return sb.toString();
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
154 }
83
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
155
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
156 private void encodeWindowsDeviceNames(StringBuilder sb) {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
157 char[] hexByte = new char[2];
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
158 int x = 0; // last segment start
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
159 final TreeSet<String> windowsReservedFilenames = new TreeSet<String>();
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
160 windowsReservedFilenames.addAll(Arrays.asList("con prn aux nul com1 com2 com3 com4 com5 com6 com7 com8 com9 lpt1 lpt2 lpt3 lpt4 lpt5 lpt6 lpt7 lpt8 lpt9".split(" ")));
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
161 do {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
162 int i = sb.indexOf("/", x);
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
163 if (i == -1) {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
164 i = sb.length();
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
165 }
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
166 // windows reserved filenames are at least of length 3
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
167 if (i - x >= 3) {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
168 boolean found = false;
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
169 if (i-x == 3 || i-x == 4) {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
170 found = windowsReservedFilenames.contains(sb.subSequence(x, i));
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
171 } else if (sb.charAt(x+3) == '.') { // implicit i-x > 3
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
172 found = windowsReservedFilenames.contains(sb.subSequence(x, x+3));
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
173 } else if (i-x > 4 && sb.charAt(x+4) == '.') {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
174 found = windowsReservedFilenames.contains(sb.subSequence(x, x+4));
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
175 }
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
176 if (found) {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
177 sb.insert(x+3, toHexByte(sb.charAt(x+2), hexByte));
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
178 sb.setCharAt(x+2, '~');
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
179 i += 2;
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
180 }
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
181 }
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
182 if (dotencode && (sb.charAt(x) == '.' || sb.charAt(x) == ' ')) {
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
183 sb.insert(x+1, toHexByte(sb.charAt(x), hexByte));
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
184 sb.setCharAt(x, '~'); // setChar *after* charAt/insert to get ~2e, not ~7e for '.'
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
185 i += 2;
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
186 }
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
187 x = i+1;
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
188 } while (x < sb.length());
a5275143664c Complete path hash calculation of fncache requirement
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 80
diff changeset
189 }
74
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
190
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
191 private static char[] toHexByte(int ch, char[] buf) {
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
192 assert buf.length > 1;
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
193 final String hexDigits = "0123456789abcdef";
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
194 buf[0] = hexDigits.charAt((ch & 0x00F0) >>> 4);
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
195 buf[1] = hexDigits.charAt(ch & 0x0F);
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
196 return buf;
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
197 }
6f1b88693d48 Complete refactoring to org.tmatesoft
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
198 }