Fossil SCM

Merged from trunk.

brickviking 2024-10-19 21:11 bv-corrections01 merge
Commit 5155a1c1d7043a69c4dfb8822535dc3eead3e33ecc3e01c13560afe0c3feebd1
3 files changed +39 +2 -2 +57 -18
--- src/checkin.c
+++ src/checkin.c
@@ -430,10 +430,11 @@
430430
**
431431
** The "fossil changes --extra" command is equivalent to "fossil extras".
432432
**
433433
** General options:
434434
** --abs-paths Display absolute pathnames
435
+** -b|--brief Show a single keyword for the status
435436
** --rel-paths Display pathnames relative to the current working
436437
** directory
437438
** --hash Verify file status using hashing rather than
438439
** relying on file mtimes
439440
** --case-sensitive BOOL Override case-sensitive setting
@@ -493,10 +494,48 @@
493494
unsigned scanFlags = 0;
494495
unsigned flags = 0;
495496
int vid, i;
496497
497498
fossil_pledge("stdio rpath wpath cpath fattr id flock tty chown");
499
+
500
+ if( find_option("brief","b",0) ){
501
+ /* The --brief or -b option is special. It cannot be used with any
502
+ ** other options. It outputs a single keyword which indicates the
503
+ ** fossil status, for use by shell scripts. The output might be
504
+ ** one of:
505
+ **
506
+ ** clean The current working directory is within a
507
+ ** unmodified fossil check-out.
508
+ **
509
+ ** dirty The pwd is within a fossil check-out that has
510
+ ** uncommitted changes
511
+ **
512
+ ** none The pwd is not within a fossil check-out.
513
+ */
514
+ int chnged;
515
+ if( g.argc>2 ){
516
+ fossil_fatal("No other arguments or options may occur with --brief");
517
+ }
518
+ if( db_open_local(0)==0 ){
519
+ fossil_print("none\n");
520
+ return;
521
+ }
522
+ vid = db_lget_int("checkout", 0);
523
+ vfile_check_signature(vid, 0);
524
+ chnged = db_int(0,
525
+ "SELECT 1 FROM vfile"
526
+ " WHERE vid=%d"
527
+ " AND (chnged>0 OR deleted OR rid==0)",
528
+ vid
529
+ );
530
+ if( chnged ){
531
+ fossil_print("dirty\n");
532
+ }else{
533
+ fossil_print("clean\n");
534
+ }
535
+ return;
536
+ }
498537
499538
/* Load affirmative flag options. */
500539
for( i=0; i<count(flagDefs); ++i ){
501540
if( (command==CHANGES || !(flagDefs[i].mask & C_CLASSIFY))
502541
&& find_option(flagDefs[i].option, 0, 0) ){
503542
--- src/checkin.c
+++ src/checkin.c
@@ -430,10 +430,11 @@
430 **
431 ** The "fossil changes --extra" command is equivalent to "fossil extras".
432 **
433 ** General options:
434 ** --abs-paths Display absolute pathnames
 
435 ** --rel-paths Display pathnames relative to the current working
436 ** directory
437 ** --hash Verify file status using hashing rather than
438 ** relying on file mtimes
439 ** --case-sensitive BOOL Override case-sensitive setting
@@ -493,10 +494,48 @@
493 unsigned scanFlags = 0;
494 unsigned flags = 0;
495 int vid, i;
496
497 fossil_pledge("stdio rpath wpath cpath fattr id flock tty chown");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
498
499 /* Load affirmative flag options. */
500 for( i=0; i<count(flagDefs); ++i ){
501 if( (command==CHANGES || !(flagDefs[i].mask & C_CLASSIFY))
502 && find_option(flagDefs[i].option, 0, 0) ){
503
--- src/checkin.c
+++ src/checkin.c
@@ -430,10 +430,11 @@
430 **
431 ** The "fossil changes --extra" command is equivalent to "fossil extras".
432 **
433 ** General options:
434 ** --abs-paths Display absolute pathnames
435 ** -b|--brief Show a single keyword for the status
436 ** --rel-paths Display pathnames relative to the current working
437 ** directory
438 ** --hash Verify file status using hashing rather than
439 ** relying on file mtimes
440 ** --case-sensitive BOOL Override case-sensitive setting
@@ -493,10 +494,48 @@
494 unsigned scanFlags = 0;
495 unsigned flags = 0;
496 int vid, i;
497
498 fossil_pledge("stdio rpath wpath cpath fattr id flock tty chown");
499
500 if( find_option("brief","b",0) ){
501 /* The --brief or -b option is special. It cannot be used with any
502 ** other options. It outputs a single keyword which indicates the
503 ** fossil status, for use by shell scripts. The output might be
504 ** one of:
505 **
506 ** clean The current working directory is within a
507 ** unmodified fossil check-out.
508 **
509 ** dirty The pwd is within a fossil check-out that has
510 ** uncommitted changes
511 **
512 ** none The pwd is not within a fossil check-out.
513 */
514 int chnged;
515 if( g.argc>2 ){
516 fossil_fatal("No other arguments or options may occur with --brief");
517 }
518 if( db_open_local(0)==0 ){
519 fossil_print("none\n");
520 return;
521 }
522 vid = db_lget_int("checkout", 0);
523 vfile_check_signature(vid, 0);
524 chnged = db_int(0,
525 "SELECT 1 FROM vfile"
526 " WHERE vid=%d"
527 " AND (chnged>0 OR deleted OR rid==0)",
528 vid
529 );
530 if( chnged ){
531 fossil_print("dirty\n");
532 }else{
533 fossil_print("clean\n");
534 }
535 return;
536 }
537
538 /* Load affirmative flag options. */
539 for( i=0; i<count(flagDefs); ++i ){
540 if( (command==CHANGES || !(flagDefs[i].mask & C_CLASSIFY))
541 && find_option(flagDefs[i].option, 0, 0) ){
542
+2 -2
--- src/file.c
+++ src/file.c
@@ -1408,13 +1408,13 @@
14081408
closedir(d);
14091409
}
14101410
fossil_path_free(zNative);
14111411
if( zResult==0 ) zResult = fossil_strdup(zPath);
14121412
return zResult;
1413
-#else /* _WIN32 */
1413
+#else /* !_WIN32 */
14141414
return win32_file_case_preferred_name(zDir,zPath);
1415
-#endif /* _WIN32 */
1415
+#endif /* !_WIN32 */
14161416
}
14171417
14181418
/*
14191419
** COMMAND: test-case-filename
14201420
**
14211421
--- src/file.c
+++ src/file.c
@@ -1408,13 +1408,13 @@
1408 closedir(d);
1409 }
1410 fossil_path_free(zNative);
1411 if( zResult==0 ) zResult = fossil_strdup(zPath);
1412 return zResult;
1413 #else /* _WIN32 */
1414 return win32_file_case_preferred_name(zDir,zPath);
1415 #endif /* _WIN32 */
1416 }
1417
1418 /*
1419 ** COMMAND: test-case-filename
1420 **
1421
--- src/file.c
+++ src/file.c
@@ -1408,13 +1408,13 @@
1408 closedir(d);
1409 }
1410 fossil_path_free(zNative);
1411 if( zResult==0 ) zResult = fossil_strdup(zPath);
1412 return zResult;
1413 #else /* !_WIN32 */
1414 return win32_file_case_preferred_name(zDir,zPath);
1415 #endif /* !_WIN32 */
1416 }
1417
1418 /*
1419 ** COMMAND: test-case-filename
1420 **
1421
+57 -18
--- src/winfile.c
+++ src/winfile.c
@@ -293,28 +293,53 @@
293293
fossil_path_free(zUtf8);
294294
}
295295
296296
/* Perform case-insensitive comparison of two UTF-16 file names. Try to load the
297297
** CompareStringOrdinal() function on Windows Vista and newer, and resort to the
298
-** lstrcmpiW() function on Windows XP.
298
+** RtlEqualUnicodeString() function on Windows XP.
299
+** The dance to invoke RtlEqualUnicodeString() is necessary because lstrcmpiW()
300
+** performs linguistic comparison, while the former performs binary comparison.
301
+** As an example, matching "ß" (U+00DF Latin Small Letter Sharp S) with "ss" is
302
+** undesirable in file name comparison, so lstrcmpiW() is only invoked in cases
303
+** that are technically impossible and contradicting all known laws of physics.
299304
*/
300
-int win32_compare_filenames_nocase(
305
+int win32_filenames_equal_nocase(
301306
const wchar_t *fn1,
302307
const wchar_t *fn2
303308
){
304309
static FARPROC fnCompareStringOrdinal;
305
- static int tried_CompareStringOrdinal;
306
- if( !tried_CompareStringOrdinal ){
310
+ static FARPROC fnRtlInitUnicodeString;
311
+ static FARPROC fnRtlEqualUnicodeString;
312
+ static int loaded_CompareStringOrdinal;
313
+ static int loaded_RtlUnicodeStringAPIs;
314
+ if( !loaded_CompareStringOrdinal ){
307315
fnCompareStringOrdinal =
308316
GetProcAddress(GetModuleHandleA("kernel32"),"CompareStringOrdinal");
309
- tried_CompareStringOrdinal = 1;
317
+ loaded_CompareStringOrdinal = 1;
310318
}
311319
if( fnCompareStringOrdinal ){
312
- return -2 + fnCompareStringOrdinal(fn1,-1,fn2,-1,1);
313
- }else{
314
- return lstrcmpiW(fn1,fn2);
320
+ return fnCompareStringOrdinal(fn1,-1,fn2,-1,1)-2==0;
321
+ }
322
+ if( !loaded_RtlUnicodeStringAPIs ){
323
+ fnRtlInitUnicodeString =
324
+ GetProcAddress(GetModuleHandleA("ntdll"),"RtlInitUnicodeString");
325
+ fnRtlEqualUnicodeString =
326
+ GetProcAddress(GetModuleHandleA("ntdll"),"RtlEqualUnicodeString");
327
+ loaded_RtlUnicodeStringAPIs = 1;
328
+ }
329
+ if( fnRtlInitUnicodeString && fnRtlEqualUnicodeString ){
330
+ struct { /* UNICODE_STRING from <ntdef.h> */
331
+ unsigned short Length;
332
+ unsigned short MaximumLength;
333
+ wchar_t *Buffer;
334
+ } u1, u2;
335
+ fnRtlInitUnicodeString(&u1,fn1);
336
+ fnRtlInitUnicodeString(&u2,fn2);
337
+ return (unsigned char)fnRtlEqualUnicodeString(&u1,&u2,1);
315338
}
339
+ /* In what kind of strange parallel universe are we? */
340
+ return lstrcmpiW(fn1,fn2)==0;
316341
}
317342
318343
/* Helper macros to deal with directory separators. */
319344
#define IS_DIRSEP(s,i) ( s[i]=='/' || s[i]=='\\' )
320345
#define NEXT_DIRSEP(s,i) while( s[i] && s[i]!='/' && s[i]!='\\' ){i++;}
@@ -347,18 +372,28 @@
347372
*/
348373
char *win32_file_case_preferred_name(
349374
const char *zBase,
350375
const char *zPath
351376
){
352
- int cchBase = strlen(zBase);
353
- int cchPath = strlen(zPath);
354
- int cchBuf = cchBase + cchPath + 2; /* + NULL + optional directory slash */
355
- int cchRes = cchPath + 1; /* + NULL */
356
- char *zBuf = fossil_malloc(cchBuf);
357
- char *zRes = fossil_malloc(cchRes);
358
- int ncUsed = 0;
377
+ int cchBase;
378
+ int cchPath;
379
+ int cchBuf;
380
+ int cchRes;
381
+ char *zBuf;
382
+ char *zRes;
383
+ int ncUsed;
359384
int i, j;
385
+ if( filenames_are_case_sensitive() ){
386
+ return fossil_strdup(zPath);
387
+ }
388
+ cchBase = strlen(zBase);
389
+ cchPath = strlen(zPath);
390
+ cchBuf = cchBase + cchPath + 2; /* + NULL + optional directory slash */
391
+ cchRes = cchPath + 1; /* + NULL */
392
+ zBuf = fossil_malloc(cchBuf);
393
+ zRes = fossil_malloc(cchRes);
394
+ ncUsed = 0;
360395
memcpy(zBuf,zBase,cchBase);
361396
if( !IS_DIRSEP(zBuf,cchBase-1) ){
362397
zBuf[cchBase++]=L'/';
363398
}
364399
memcpy(zBuf+cchBase,zPath,cchPath+1);
@@ -372,10 +407,14 @@
372407
int cchComp;
373408
char chSep;
374409
int fDone;
375410
if( IS_DIRSEP(zBuf,i) ){
376411
zRes[ncUsed++] = zBuf[i];
412
+ if( ncUsed+2>cchRes ){ /* Directory slash + NULL*/
413
+ cchRes += 32; /* Overprovisioning. */
414
+ zRes = fossil_realloc(zRes,cchRes);
415
+ }
377416
i = j = i+1;
378417
continue;
379418
}
380419
NEXT_DIRSEP(zBuf,j);
381420
fDone = zBuf[j]==0;
@@ -385,20 +424,20 @@
385424
hFind = FindFirstFileW(wzBuf,&fd);
386425
if( hFind!=INVALID_HANDLE_VALUE ){
387426
wchar_t *wzComp = fossil_utf8_to_path(zComp,0);
388427
FindClose(hFind);
389428
/* Test fd.cFileName, not fd.cAlternateFileName (classic 8.3 format). */
390
- if( win32_compare_filenames_nocase(wzComp,fd.cFileName)==0 ){
429
+ if( win32_filenames_equal_nocase(wzComp,fd.cFileName) ){
391430
zCompBuf = fossil_path_to_utf8(fd.cFileName);
392431
zComp = zCompBuf;
393432
}
394433
fossil_path_free(wzComp);
395434
}
396435
fossil_path_free(wzBuf);
397436
cchComp = strlen(zComp);
398
- if( ncUsed+cchComp+1>cchRes ){
399
- cchRes = ncUsed + cchComp + 32; /* While at it, add some extra space. */
437
+ if( ncUsed+cchComp+1>cchRes ){ /* Current component + NULL */
438
+ cchRes += cchComp + 32; /* Overprovisioning. */
400439
zRes = fossil_realloc(zRes,cchRes);
401440
}
402441
memcpy(zRes+ncUsed,zComp,cchComp);
403442
ncUsed += cchComp;
404443
if( zCompBuf ){
405444
--- src/winfile.c
+++ src/winfile.c
@@ -293,28 +293,53 @@
293 fossil_path_free(zUtf8);
294 }
295
296 /* Perform case-insensitive comparison of two UTF-16 file names. Try to load the
297 ** CompareStringOrdinal() function on Windows Vista and newer, and resort to the
298 ** lstrcmpiW() function on Windows XP.
 
 
 
 
 
299 */
300 int win32_compare_filenames_nocase(
301 const wchar_t *fn1,
302 const wchar_t *fn2
303 ){
304 static FARPROC fnCompareStringOrdinal;
305 static int tried_CompareStringOrdinal;
306 if( !tried_CompareStringOrdinal ){
 
 
 
307 fnCompareStringOrdinal =
308 GetProcAddress(GetModuleHandleA("kernel32"),"CompareStringOrdinal");
309 tried_CompareStringOrdinal = 1;
310 }
311 if( fnCompareStringOrdinal ){
312 return -2 + fnCompareStringOrdinal(fn1,-1,fn2,-1,1);
313 }else{
314 return lstrcmpiW(fn1,fn2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315 }
 
 
316 }
317
318 /* Helper macros to deal with directory separators. */
319 #define IS_DIRSEP(s,i) ( s[i]=='/' || s[i]=='\\' )
320 #define NEXT_DIRSEP(s,i) while( s[i] && s[i]!='/' && s[i]!='\\' ){i++;}
@@ -347,18 +372,28 @@
347 */
348 char *win32_file_case_preferred_name(
349 const char *zBase,
350 const char *zPath
351 ){
352 int cchBase = strlen(zBase);
353 int cchPath = strlen(zPath);
354 int cchBuf = cchBase + cchPath + 2; /* + NULL + optional directory slash */
355 int cchRes = cchPath + 1; /* + NULL */
356 char *zBuf = fossil_malloc(cchBuf);
357 char *zRes = fossil_malloc(cchRes);
358 int ncUsed = 0;
359 int i, j;
 
 
 
 
 
 
 
 
 
 
360 memcpy(zBuf,zBase,cchBase);
361 if( !IS_DIRSEP(zBuf,cchBase-1) ){
362 zBuf[cchBase++]=L'/';
363 }
364 memcpy(zBuf+cchBase,zPath,cchPath+1);
@@ -372,10 +407,14 @@
372 int cchComp;
373 char chSep;
374 int fDone;
375 if( IS_DIRSEP(zBuf,i) ){
376 zRes[ncUsed++] = zBuf[i];
 
 
 
 
377 i = j = i+1;
378 continue;
379 }
380 NEXT_DIRSEP(zBuf,j);
381 fDone = zBuf[j]==0;
@@ -385,20 +424,20 @@
385 hFind = FindFirstFileW(wzBuf,&fd);
386 if( hFind!=INVALID_HANDLE_VALUE ){
387 wchar_t *wzComp = fossil_utf8_to_path(zComp,0);
388 FindClose(hFind);
389 /* Test fd.cFileName, not fd.cAlternateFileName (classic 8.3 format). */
390 if( win32_compare_filenames_nocase(wzComp,fd.cFileName)==0 ){
391 zCompBuf = fossil_path_to_utf8(fd.cFileName);
392 zComp = zCompBuf;
393 }
394 fossil_path_free(wzComp);
395 }
396 fossil_path_free(wzBuf);
397 cchComp = strlen(zComp);
398 if( ncUsed+cchComp+1>cchRes ){
399 cchRes = ncUsed + cchComp + 32; /* While at it, add some extra space. */
400 zRes = fossil_realloc(zRes,cchRes);
401 }
402 memcpy(zRes+ncUsed,zComp,cchComp);
403 ncUsed += cchComp;
404 if( zCompBuf ){
405
--- src/winfile.c
+++ src/winfile.c
@@ -293,28 +293,53 @@
293 fossil_path_free(zUtf8);
294 }
295
296 /* Perform case-insensitive comparison of two UTF-16 file names. Try to load the
297 ** CompareStringOrdinal() function on Windows Vista and newer, and resort to the
298 ** RtlEqualUnicodeString() function on Windows XP.
299 ** The dance to invoke RtlEqualUnicodeString() is necessary because lstrcmpiW()
300 ** performs linguistic comparison, while the former performs binary comparison.
301 ** As an example, matching "ß" (U+00DF Latin Small Letter Sharp S) with "ss" is
302 ** undesirable in file name comparison, so lstrcmpiW() is only invoked in cases
303 ** that are technically impossible and contradicting all known laws of physics.
304 */
305 int win32_filenames_equal_nocase(
306 const wchar_t *fn1,
307 const wchar_t *fn2
308 ){
309 static FARPROC fnCompareStringOrdinal;
310 static FARPROC fnRtlInitUnicodeString;
311 static FARPROC fnRtlEqualUnicodeString;
312 static int loaded_CompareStringOrdinal;
313 static int loaded_RtlUnicodeStringAPIs;
314 if( !loaded_CompareStringOrdinal ){
315 fnCompareStringOrdinal =
316 GetProcAddress(GetModuleHandleA("kernel32"),"CompareStringOrdinal");
317 loaded_CompareStringOrdinal = 1;
318 }
319 if( fnCompareStringOrdinal ){
320 return fnCompareStringOrdinal(fn1,-1,fn2,-1,1)-2==0;
321 }
322 if( !loaded_RtlUnicodeStringAPIs ){
323 fnRtlInitUnicodeString =
324 GetProcAddress(GetModuleHandleA("ntdll"),"RtlInitUnicodeString");
325 fnRtlEqualUnicodeString =
326 GetProcAddress(GetModuleHandleA("ntdll"),"RtlEqualUnicodeString");
327 loaded_RtlUnicodeStringAPIs = 1;
328 }
329 if( fnRtlInitUnicodeString && fnRtlEqualUnicodeString ){
330 struct { /* UNICODE_STRING from <ntdef.h> */
331 unsigned short Length;
332 unsigned short MaximumLength;
333 wchar_t *Buffer;
334 } u1, u2;
335 fnRtlInitUnicodeString(&u1,fn1);
336 fnRtlInitUnicodeString(&u2,fn2);
337 return (unsigned char)fnRtlEqualUnicodeString(&u1,&u2,1);
338 }
339 /* In what kind of strange parallel universe are we? */
340 return lstrcmpiW(fn1,fn2)==0;
341 }
342
343 /* Helper macros to deal with directory separators. */
344 #define IS_DIRSEP(s,i) ( s[i]=='/' || s[i]=='\\' )
345 #define NEXT_DIRSEP(s,i) while( s[i] && s[i]!='/' && s[i]!='\\' ){i++;}
@@ -347,18 +372,28 @@
372 */
373 char *win32_file_case_preferred_name(
374 const char *zBase,
375 const char *zPath
376 ){
377 int cchBase;
378 int cchPath;
379 int cchBuf;
380 int cchRes;
381 char *zBuf;
382 char *zRes;
383 int ncUsed;
384 int i, j;
385 if( filenames_are_case_sensitive() ){
386 return fossil_strdup(zPath);
387 }
388 cchBase = strlen(zBase);
389 cchPath = strlen(zPath);
390 cchBuf = cchBase + cchPath + 2; /* + NULL + optional directory slash */
391 cchRes = cchPath + 1; /* + NULL */
392 zBuf = fossil_malloc(cchBuf);
393 zRes = fossil_malloc(cchRes);
394 ncUsed = 0;
395 memcpy(zBuf,zBase,cchBase);
396 if( !IS_DIRSEP(zBuf,cchBase-1) ){
397 zBuf[cchBase++]=L'/';
398 }
399 memcpy(zBuf+cchBase,zPath,cchPath+1);
@@ -372,10 +407,14 @@
407 int cchComp;
408 char chSep;
409 int fDone;
410 if( IS_DIRSEP(zBuf,i) ){
411 zRes[ncUsed++] = zBuf[i];
412 if( ncUsed+2>cchRes ){ /* Directory slash + NULL*/
413 cchRes += 32; /* Overprovisioning. */
414 zRes = fossil_realloc(zRes,cchRes);
415 }
416 i = j = i+1;
417 continue;
418 }
419 NEXT_DIRSEP(zBuf,j);
420 fDone = zBuf[j]==0;
@@ -385,20 +424,20 @@
424 hFind = FindFirstFileW(wzBuf,&fd);
425 if( hFind!=INVALID_HANDLE_VALUE ){
426 wchar_t *wzComp = fossil_utf8_to_path(zComp,0);
427 FindClose(hFind);
428 /* Test fd.cFileName, not fd.cAlternateFileName (classic 8.3 format). */
429 if( win32_filenames_equal_nocase(wzComp,fd.cFileName) ){
430 zCompBuf = fossil_path_to_utf8(fd.cFileName);
431 zComp = zCompBuf;
432 }
433 fossil_path_free(wzComp);
434 }
435 fossil_path_free(wzBuf);
436 cchComp = strlen(zComp);
437 if( ncUsed+cchComp+1>cchRes ){ /* Current component + NULL */
438 cchRes += cchComp + 32; /* Overprovisioning. */
439 zRes = fossil_realloc(zRes,cchRes);
440 }
441 memcpy(zRes+ncUsed,zComp,cchComp);
442 ncUsed += cchComp;
443 if( zCompBuf ){
444

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button