comparison src/org/tmatesoft/hg/repo/HgManifest.java @ 372:155c1893bda4

Issue 22: UnsupportedOperationException on empty manifest entry
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 06 Jan 2012 00:42:15 +0300
parents 8107b95f4280
children 6150555eb41d
comparison
equal deleted inserted replaced
371:aa2e589d4e84 372:155c1893bda4
322 try { 322 try {
323 if (!inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision)) { 323 if (!inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision)) {
324 iterateControl.stop(); 324 iterateControl.stop();
325 return; 325 return;
326 } 326 }
327 Path fname = null; 327 if (!da.isEmpty()) {
328 Flags flags = null; 328 // although unlikely, manifest entry may be empty, when all files have been deleted from the repository
329 Nodeid nid = null; 329 Path fname = null;
330 int i; 330 Flags flags = null;
331 byte[] data = da.byteArray(); 331 Nodeid nid = null;
332 for (i = 0; i < actualLen; i++) { 332 int i;
333 int x = i; 333 byte[] data = da.byteArray();
334 for( ; data[i] != '\n' && i < actualLen; i++) { 334 for (i = 0; i < actualLen; i++) {
335 if (fname == null && data[i] == 0) { 335 int x = i;
336 PathProxy px = fnamePool.unify(new PathProxy(data, x, i - x)); 336 for( ; data[i] != '\n' && i < actualLen; i++) {
337 // if (cached = fnamePool.unify(px))== px then cacheMiss, else cacheHit 337 if (fname == null && data[i] == 0) {
338 // cpython 0..10k: hits: 15 989 152, misses: 3020 338 PathProxy px = fnamePool.unify(new PathProxy(data, x, i - x));
339 fname = px.freeze(); 339 // if (cached = fnamePool.unify(px))== px then cacheMiss, else cacheHit
340 x = i+1; 340 // cpython 0..10k: hits: 15 989 152, misses: 3020
341 fname = px.freeze();
342 x = i+1;
343 }
341 } 344 }
345 if (i < actualLen) {
346 assert data[i] == '\n';
347 int nodeidLen = i - x < 40 ? i-x : 40; // if > 40, there are flags
348 DigestHelper.ascii2bin(data, x, nodeidLen, nodeidLookupBuffer); // ignore return value as it's unlikely to have NULL in manifest
349 nid = new Nodeid(nodeidLookupBuffer, false); // this Nodeid is for pool lookup only, mock object
350 Nodeid cached = nodeidPool.unify(nid);
351 if (cached == nid) {
352 // buffer now belongs to the cached nodeid
353 nodeidLookupBuffer = new byte[20];
354 } else {
355 nid = cached; // use existing version, discard the lookup object
356 } // for cpython 0..10k, cache hits are 15 973 301, vs 18871 misses.
357 thisRevPool.record(nid); // memorize revision for the next iteration.
358 if (nodeidLen + x < i) {
359 // 'x' and 'l' for executable bits and symlinks?
360 // hg --debug manifest shows 644 for each regular file in my repo
361 // for cpython 0..10k, there are 4361062 flag checks, and there's only 1 unique flag
362 flags = Flags.parse(data, x + nodeidLen, i-x-nodeidLen);
363 } else {
364 flags = null;
365 }
366 boolean good2go;
367 if (inspector2 == null) {
368 String flagString = flags == null ? null : flags.nativeString();
369 good2go = inspector.next(nid, fname.toString(), flagString);
370 } else {
371 good2go = inspector2.next(nid, fname, flags);
372 }
373 if (!good2go) {
374 iterateControl.stop();
375 return;
376 }
377 }
378 nid = null;
379 fname = null;
380 flags = null;
342 } 381 }
343 if (i < actualLen) {
344 assert data[i] == '\n';
345 int nodeidLen = i - x < 40 ? i-x : 40; // if > 40, there are flags
346 DigestHelper.ascii2bin(data, x, nodeidLen, nodeidLookupBuffer); // ignore return value as it's unlikely to have NULL in manifest
347 nid = new Nodeid(nodeidLookupBuffer, false); // this Nodeid is for pool lookup only, mock object
348 Nodeid cached = nodeidPool.unify(nid);
349 if (cached == nid) {
350 // buffer now belongs to the cached nodeid
351 nodeidLookupBuffer = new byte[20];
352 } else {
353 nid = cached; // use existing version, discard the lookup object
354 } // for cpython 0..10k, cache hits are 15 973 301, vs 18871 misses.
355 thisRevPool.record(nid); // memorize revision for the next iteration.
356 if (nodeidLen + x < i) {
357 // 'x' and 'l' for executable bits and symlinks?
358 // hg --debug manifest shows 644 for each regular file in my repo
359 // for cpython 0..10k, there are 4361062 flag checks, and there's only 1 unique flag
360 flags = Flags.parse(data, x + nodeidLen, i-x-nodeidLen);
361 } else {
362 flags = null;
363 }
364 boolean good2go;
365 if (inspector2 == null) {
366 String flagString = flags == null ? null : flags.nativeString();
367 good2go = inspector.next(nid, fname.toString(), flagString);
368 } else {
369 good2go = inspector2.next(nid, fname, flags);
370 }
371 if (!good2go) {
372 iterateControl.stop();
373 return;
374 }
375 }
376 nid = null;
377 fname = null;
378 flags = null;
379 } 382 }
380 if (!inspector.end(revisionNumber)) { 383 if (!inspector.end(revisionNumber)) {
381 iterateControl.stop(); 384 iterateControl.stop();
382 return; 385 return;
383 } 386 }