1 /* 2 * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com> 3 * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org> 4 * and other copyright owners as documented in the project's IP log. 5 * 6 * This program and the accompanying materials are made available 7 * under the terms of the Eclipse Distribution License v1.0 which 8 * accompanies this distribution, is reproduced below, and is 9 * available at http://www.eclipse.org/org/documents/edl-v10.php 10 * 11 * All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or 14 * without modification, are permitted provided that the following 15 * conditions are met: 16 * 17 * - Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials provided 23 * with the distribution. 24 * 25 * - Neither the name of the Eclipse Foundation, Inc. nor the 26 * names of its contributors may be used to endorse or promote 27 * products derived from this software without specific prior 28 * written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 31 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 32 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 37 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 39 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 42 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 */ 44 45 package org.eclipse.jgit.lib; 46 47 import java.io.IOException; 48 import java.io.OutputStream; 49 50 /** 51 * Constants describing various file modes recognized by GIT. 52 * <p> 53 * GIT uses a subset of the available UNIX file permission bits. The 54 * <code>FileMode</code> class provides access to constants defining the modes 55 * actually used by GIT. 56 * </p> 57 */ 58 public abstract class FileMode { 59 /** 60 * Mask to apply to a file mode to obtain its type bits. 61 * 62 * @see #TYPE_TREE 63 * @see #TYPE_SYMLINK 64 * @see #TYPE_FILE 65 * @see #TYPE_GITLINK 66 * @see #TYPE_MISSING 67 */ 68 public static final int TYPE_MASK = 0170000; 69 70 /** Bit pattern for {@link #TYPE_MASK} matching {@link #TREE}. */ 71 public static final int TYPE_TREE = 0040000; 72 73 /** Bit pattern for {@link #TYPE_MASK} matching {@link #SYMLINK}. */ 74 public static final int TYPE_SYMLINK = 0120000; 75 76 /** Bit pattern for {@link #TYPE_MASK} matching {@link #REGULAR_FILE}. */ 77 public static final int TYPE_FILE = 0100000; 78 79 /** Bit pattern for {@link #TYPE_MASK} matching {@link #GITLINK}. */ 80 public static final int TYPE_GITLINK = 0160000; 81 82 /** Bit pattern for {@link #TYPE_MASK} matching {@link #MISSING}. */ 83 public static final int TYPE_MISSING = 0000000; 84 85 /** 86 * Mode indicating an entry is a tree (aka directory). 87 */ 88 public static final FileModee.html#FileMode">FileMode TREE = new FileMode(TYPE_TREE, 89 Constants.OBJ_TREE) { 90 @Override 91 @SuppressWarnings("NonOverridingEquals") 92 public boolean equals(int modeBits) { 93 return (modeBits & TYPE_MASK) == TYPE_TREE; 94 } 95 }; 96 97 /** Mode indicating an entry is a symbolic link. */ 98 public static final FileModetml#FileMode">FileMode SYMLINK = new FileMode(TYPE_SYMLINK, 99 Constants.OBJ_BLOB) { 100 @Override 101 @SuppressWarnings("NonOverridingEquals") 102 public boolean equals(int modeBits) { 103 return (modeBits & TYPE_MASK) == TYPE_SYMLINK; 104 } 105 }; 106 107 /** Mode indicating an entry is a non-executable file. */ 108 public static final FileModeileMode">FileMode REGULAR_FILE = new FileMode(0100644, 109 Constants.OBJ_BLOB) { 110 @Override 111 @SuppressWarnings("NonOverridingEquals") 112 public boolean equals(int modeBits) { 113 return (modeBits & TYPE_MASK) == TYPE_FILE && (modeBits & 0111) == 0; 114 } 115 }; 116 117 /** Mode indicating an entry is an executable file. */ 118 public static final FileModeMode">FileMode EXECUTABLE_FILE = new FileMode(0100755, 119 Constants.OBJ_BLOB) { 120 @Override 121 @SuppressWarnings("NonOverridingEquals") 122 public boolean equals(int modeBits) { 123 return (modeBits & TYPE_MASK) == TYPE_FILE && (modeBits & 0111) != 0; 124 } 125 }; 126 127 /** Mode indicating an entry is a submodule commit in another repository. */ 128 public static final FileModetml#FileMode">FileMode GITLINK = new FileMode(TYPE_GITLINK, 129 Constants.OBJ_COMMIT) { 130 @Override 131 @SuppressWarnings("NonOverridingEquals") 132 public boolean equals(int modeBits) { 133 return (modeBits & TYPE_MASK) == TYPE_GITLINK; 134 } 135 }; 136 137 /** Mode indicating an entry is missing during parallel walks. */ 138 public static final FileModetml#FileMode">FileMode MISSING = new FileMode(TYPE_MISSING, 139 Constants.OBJ_BAD) { 140 @Override 141 @SuppressWarnings("NonOverridingEquals") 142 public boolean equals(int modeBits) { 143 return modeBits == 0; 144 } 145 }; 146 147 /** 148 * Convert a set of mode bits into a FileMode enumerated value. 149 * 150 * @param bits 151 * the mode bits the caller has somehow obtained. 152 * @return the FileMode instance that represents the given bits. 153 */ 154 public static final FileMode fromBits(int bits) { 155 switch (bits & TYPE_MASK) { 156 case TYPE_MISSING: 157 if (bits == 0) 158 return MISSING; 159 break; 160 case TYPE_TREE: 161 return TREE; 162 case TYPE_FILE: 163 if ((bits & 0111) != 0) 164 return EXECUTABLE_FILE; 165 return REGULAR_FILE; 166 case TYPE_SYMLINK: 167 return SYMLINK; 168 case TYPE_GITLINK: 169 return GITLINK; 170 } 171 172 return new FileMode(bits, Constants.OBJ_BAD) { 173 @Override 174 @SuppressWarnings("NonOverridingEquals") 175 public boolean equals(int a) { 176 return bits == a; 177 } 178 }; 179 } 180 181 private final byte[] octalBytes; 182 183 private final int modeBits; 184 185 private final int objectType; 186 187 private FileMode(int mode, int expType) { 188 modeBits = mode; 189 objectType = expType; 190 if (mode != 0) { 191 final byte[] tmp = new byte[10]; 192 int p = tmp.length; 193 194 while (mode != 0) { 195 tmp[--p] = (byte) ('0' + (mode & 07)); 196 mode >>= 3; 197 } 198 199 octalBytes = new byte[tmp.length - p]; 200 for (int k = 0; k < octalBytes.length; k++) { 201 octalBytes[k] = tmp[p + k]; 202 } 203 } else { 204 octalBytes = new byte[] { '0' }; 205 } 206 } 207 208 /** 209 * Test a file mode for equality with this 210 * {@link org.eclipse.jgit.lib.FileMode} object. 211 * 212 * @param modebits 213 * a int. 214 * @return true if the mode bits represent the same mode as this object 215 */ 216 @SuppressWarnings("NonOverridingEquals") 217 public abstract boolean equals(int modebits); 218 219 /** 220 * Copy this mode as a sequence of octal US-ASCII bytes. 221 * <p> 222 * The mode is copied as a sequence of octal digits using the US-ASCII 223 * character encoding. The sequence does not use a leading '0' prefix to 224 * indicate octal notation. This method is suitable for generation of a mode 225 * string within a GIT tree object. 226 * </p> 227 * 228 * @param os 229 * stream to copy the mode to. 230 * @throws java.io.IOException 231 * the stream encountered an error during the copy. 232 */ 233 public void copyTo(OutputStream os) throws IOException { 234 os.write(octalBytes); 235 } 236 237 /** 238 * Copy this mode as a sequence of octal US-ASCII bytes. 239 * 240 * The mode is copied as a sequence of octal digits using the US-ASCII 241 * character encoding. The sequence does not use a leading '0' prefix to 242 * indicate octal notation. This method is suitable for generation of a mode 243 * string within a GIT tree object. 244 * 245 * @param buf 246 * buffer to copy the mode to. 247 * @param ptr 248 * position within {@code buf} for first digit. 249 */ 250 public void copyTo(byte[] buf, int ptr) { 251 System.arraycopy(octalBytes, 0, buf, ptr, octalBytes.length); 252 } 253 254 /** 255 * Copy the number of bytes written by {@link #copyTo(OutputStream)}. 256 * 257 * @return the number of bytes written by {@link #copyTo(OutputStream)}. 258 */ 259 public int copyToLength() { 260 return octalBytes.length; 261 } 262 263 /** 264 * Get the object type that should appear for this type of mode. 265 * <p> 266 * See the object type constants in {@link org.eclipse.jgit.lib.Constants}. 267 * 268 * @return one of the well known object type constants. 269 */ 270 public int getObjectType() { 271 return objectType; 272 } 273 274 /** 275 * {@inheritDoc} 276 * <p> 277 * Format this mode as an octal string (for debugging only). 278 */ 279 @Override 280 public String toString() { 281 return Integer.toOctalString(modeBits); 282 } 283 284 /** 285 * Get the mode bits as an integer. 286 * 287 * @return The mode bits as an integer. 288 */ 289 public int getBits() { 290 return modeBits; 291 } 292 }