test-status.t 17.6 KB
Newer Older
1
#testcases dirstate-v1 dirstate-v2
2
3
4
5
6
7

#if dirstate-v2
  $ echo '[format]' >> $HGRCPATH
  $ echo 'exp-dirstate-v2=1' >> $HGRCPATH
#endif

Nicolas Dumazet's avatar
Nicolas Dumazet committed
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
  $ hg init repo1
  $ cd repo1
  $ mkdir a b a/1 b/1 b/2
  $ touch in_root a/in_a b/in_b a/1/in_a_1 b/1/in_b_1 b/2/in_b_2

hg status in repo root:

  $ hg status
  ? a/1/in_a_1
  ? a/in_a
  ? b/1/in_b_1
  ? b/2/in_b_2
  ? b/in_b
  ? in_root

hg status . in repo root:

  $ hg status .
  ? a/1/in_a_1
  ? a/in_a
  ? b/1/in_b_1
  ? b/2/in_b_2
  ? b/in_b
  ? in_root

  $ hg status --cwd a
  ? a/1/in_a_1
  ? a/in_a
  ? b/1/in_b_1
  ? b/2/in_b_2
  ? b/in_b
  ? in_root
  $ hg status --cwd a .
  ? 1/in_a_1
  ? in_a
  $ hg status --cwd a ..
  ? 1/in_a_1
  ? in_a
  ? ../b/1/in_b_1
  ? ../b/2/in_b_2
  ? ../b/in_b
  ? ../in_root

  $ hg status --cwd b
  ? a/1/in_a_1
  ? a/in_a
  ? b/1/in_b_1
  ? b/2/in_b_2
  ? b/in_b
  ? in_root
  $ hg status --cwd b .
  ? 1/in_b_1
  ? 2/in_b_2
  ? in_b
  $ hg status --cwd b ..
  ? ../a/1/in_a_1
  ? ../a/in_a
  ? 1/in_b_1
  ? 2/in_b_2
  ? in_b
  ? ../in_root

  $ hg status --cwd a/1
  ? a/1/in_a_1
  ? a/in_a
  ? b/1/in_b_1
  ? b/2/in_b_2
  ? b/in_b
  ? in_root
  $ hg status --cwd a/1 .
  ? in_a_1
  $ hg status --cwd a/1 ..
  ? in_a_1
  ? ../in_a

  $ hg status --cwd b/1
  ? a/1/in_a_1
  ? a/in_a
  ? b/1/in_b_1
  ? b/2/in_b_2
  ? b/in_b
  ? in_root
  $ hg status --cwd b/1 .
  ? in_b_1
  $ hg status --cwd b/1 ..
  ? in_b_1
  ? ../2/in_b_2
  ? ../in_b

  $ hg status --cwd b/2
  ? a/1/in_a_1
  ? a/in_a
  ? b/1/in_b_1
  ? b/2/in_b_2
  ? b/in_b
  ? in_root
  $ hg status --cwd b/2 .
  ? in_b_2
  $ hg status --cwd b/2 ..
  ? ../1/in_b_1
  ? in_b_2
  ? ../in_b
110
111
112
113
114
115
116

combining patterns with root and patterns without a root works

  $ hg st a/in_a re:.*b$
  ? a/in_a
  ? b/in_b

117
118
tweaking defaults works
  $ hg status --cwd a --config ui.tweakdefaults=yes
119
120
121
122
123
  ? 1/in_a_1
  ? in_a
  ? ../b/1/in_b_1
  ? ../b/2/in_b_2
  ? ../b/in_b
124
125
126
127
128
129
130
131
132
  ? ../in_root
  $ HGPLAIN=1 hg status --cwd a --config ui.tweakdefaults=yes
  ? a/1/in_a_1 (glob)
  ? a/in_a (glob)
  ? b/1/in_b_1 (glob)
  ? b/2/in_b_2 (glob)
  ? b/in_b (glob)
  ? in_root
  $ HGPLAINEXCEPT=tweakdefaults hg status --cwd a --config ui.tweakdefaults=yes
133
134
135
136
137
  ? 1/in_a_1
  ? in_a
  ? ../b/1/in_b_1
  ? ../b/2/in_b_2
  ? ../b/in_b
138
  ? ../in_root (glob)
139

140
141
relative paths can be requested

142
  $ hg status --cwd a --config ui.relative-paths=yes
143
144
145
146
147
148
149
  ? 1/in_a_1
  ? in_a
  ? ../b/1/in_b_1
  ? ../b/2/in_b_2
  ? ../b/in_b
  ? ../in_root

150
151
152
153
154
155
156
  $ hg status --cwd a . --config ui.relative-paths=legacy
  ? 1/in_a_1
  ? in_a
  $ hg status --cwd a . --config ui.relative-paths=no
  ? a/1/in_a_1
  ? a/in_a

157
158
159
160
161
commands.status.relative overrides ui.relative-paths

  $ cat >> $HGRCPATH <<EOF
  > [ui]
  > relative-paths = False
162
163
164
165
166
167
168
169
170
171
172
  > [commands]
  > status.relative = True
  > EOF
  $ hg status --cwd a
  ? 1/in_a_1
  ? in_a
  ? ../b/1/in_b_1
  ? ../b/2/in_b_2
  ? ../b/in_b
  ? ../in_root
  $ HGPLAIN=1 hg status --cwd a
Matt Harbison's avatar
Matt Harbison committed
173
174
175
176
177
  ? a/1/in_a_1 (glob)
  ? a/in_a (glob)
  ? b/1/in_b_1 (glob)
  ? b/2/in_b_2 (glob)
  ? b/in_b (glob)
178
179
  ? in_root

180
181
182
183
184
185
if relative paths are explicitly off, tweakdefaults doesn't change it
  $ cat >> $HGRCPATH <<EOF
  > [commands]
  > status.relative = False
  > EOF
  $ hg status --cwd a --config ui.tweakdefaults=yes
186
187
188
189
190
  ? a/1/in_a_1
  ? a/in_a
  ? b/1/in_b_1
  ? b/2/in_b_2
  ? b/in_b
191
192
  ? in_root

Nicolas Dumazet's avatar
Nicolas Dumazet committed
193
194
195
196
197
198
  $ cd ..

  $ hg init repo2
  $ cd repo2
  $ touch modified removed deleted ignored
  $ echo "^ignored$" > .hgignore
199
  $ hg ci -A -m 'initial checkin'
Nicolas Dumazet's avatar
Nicolas Dumazet committed
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  adding .hgignore
  adding deleted
  adding modified
  adding removed
  $ touch modified added unknown ignored
  $ hg add added
  $ hg remove removed
  $ rm deleted

hg status:

  $ hg status
  A added
  R removed
  ! deleted
  ? unknown

hg status modified added removed deleted unknown never-existed ignored:

  $ hg status modified added removed deleted unknown never-existed ignored
220
  never-existed: * (glob)
Nicolas Dumazet's avatar
Nicolas Dumazet committed
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
  A added
  R removed
  ! deleted
  ? unknown

  $ hg copy modified copied

hg status -C:

  $ hg status -C
  A added
  A copied
    modified
  R removed
  ! deleted
  ? unknown

hg status -A:

  $ hg status -A
  A added
  A copied
    modified
  R removed
  ! deleted
  ? unknown
  I ignored
  C .hgignore
  C modified

251
252
253
254
255
256
257
258
259
260
  $ hg status -A -T '{status} {path} {node|shortest}\n'
  A added ffff
  A copied ffff
  R removed ffff
  ! deleted ffff
  ? unknown ffff
  I ignored ffff
  C .hgignore ffff
  C modified ffff

261
262
263
  $ hg status -A -Tjson
  [
   {
264
    "itemtype": "file",
265
266
267
268
    "path": "added",
    "status": "A"
   },
   {
269
    "itemtype": "file",
270
    "path": "copied",
271
    "source": "modified",
272
273
274
    "status": "A"
   },
   {
275
    "itemtype": "file",
276
277
278
279
    "path": "removed",
    "status": "R"
   },
   {
280
    "itemtype": "file",
281
282
283
284
    "path": "deleted",
    "status": "!"
   },
   {
285
    "itemtype": "file",
286
287
288
289
    "path": "unknown",
    "status": "?"
   },
   {
290
    "itemtype": "file",
291
292
293
294
    "path": "ignored",
    "status": "I"
   },
   {
295
    "itemtype": "file",
296
297
298
299
    "path": ".hgignore",
    "status": "C"
   },
   {
300
    "itemtype": "file",
301
302
303
304
    "path": "modified",
    "status": "C"
   }
  ]
Nicolas Dumazet's avatar
Nicolas Dumazet committed
305

Matt Mackall's avatar
Matt Mackall committed
306
  $ hg status -A -Tpickle > pickle
307
  >>> from __future__ import print_function
308
309
  >>> from mercurial import util
  >>> pickle = util.pickle
Mark Thomas's avatar
Mark Thomas committed
310
311
312
313
314
315
316
317
318
319
320
  >>> data = sorted((x[b'status'].decode(), x[b'path'].decode()) for x in pickle.load(open("pickle", r"rb")))
  >>> for s, p in data: print("%s %s" % (s, p))
  ! deleted
  ? pickle
  ? unknown
  A added
  A copied
  C .hgignore
  C modified
  I ignored
  R removed
Matt Mackall's avatar
Matt Mackall committed
321
322
  $ rm pickle

Nicolas Dumazet's avatar
Nicolas Dumazet committed
323
324
325
326
  $ echo "^ignoreddir$" > .hgignore
  $ mkdir ignoreddir
  $ touch ignoreddir/file

327
328
Test templater support:

329
  $ hg status -AT "[{status}]\t{if(source, '{source} -> ')}{path}\n"
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  [M]	.hgignore
  [A]	added
  [A]	modified -> copied
  [R]	removed
  [!]	deleted
  [?]	ignored
  [?]	unknown
  [I]	ignoreddir/file
  [C]	modified
  $ hg status -AT default
  M .hgignore
  A added
  A copied
    modified
  R removed
  ! deleted
  ? ignored
  ? unknown
  I ignoreddir/file
  C modified
  $ hg status -T compact
  abort: "status" not in template map
  [255]

Nicolas Dumazet's avatar
Nicolas Dumazet committed
354
355
356
357
358
359
360
361
362
363
hg status ignoreddir/file:

  $ hg status ignoreddir/file

hg status -i ignoreddir/file:

  $ hg status -i ignoreddir/file
  I ignoreddir/file
  $ cd ..

364
Check 'status -q' and some combinations
Nicolas Dumazet's avatar
Nicolas Dumazet committed
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381

  $ hg init repo3
  $ cd repo3
  $ touch modified removed deleted ignored
  $ echo "^ignored$" > .hgignore
  $ hg commit -A -m 'initial checkin'
  adding .hgignore
  adding deleted
  adding modified
  adding removed
  $ touch added unknown ignored
  $ hg add added
  $ echo "test" >> modified
  $ hg remove removed
  $ rm deleted
  $ hg copy modified copied

382
383
384
385
386
387
388
389
390
391
392
Specify working directory revision explicitly, that should be the same as
"hg status"

  $ hg status --change "wdir()"
  M modified
  A added
  A copied
  R removed
  ! deleted
  ? unknown

393
394
395
Run status with 2 different flags.
Check if result is the same or different.
If result is not as expected, raise error
Nicolas Dumazet's avatar
Nicolas Dumazet committed
396
397

  $ assert() {
398
399
400
401
402
  >     hg status $1 > ../a
  >     hg status $2 > ../b
  >     if diff ../a ../b > /dev/null; then
  >         out=0
  >     else
Nicolas Dumazet's avatar
Nicolas Dumazet committed
403
404
405
406
407
408
409
410
411
412
413
414
  >         out=1
  >     fi
  >     if [ $3 -eq 0 ]; then
  >         df="same"
  >     else
  >         df="different"
  >     fi
  >     if [ $out -ne $3 ]; then
  >         echo "Error on $1 and $2, should be $df."
  >     fi
  > }

415
Assert flag1 flag2 [0-same | 1-different]
Nicolas Dumazet's avatar
Nicolas Dumazet committed
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431

  $ assert "-q" "-mard"      0
  $ assert "-A" "-marduicC"  0
  $ assert "-qA" "-mardcC"   0
  $ assert "-qAui" "-A"      0
  $ assert "-qAu" "-marducC" 0
  $ assert "-qAi" "-mardicC" 0
  $ assert "-qu" "-u"        0
  $ assert "-q" "-u"         1
  $ assert "-m" "-a"         1
  $ assert "-r" "-d"         1
  $ cd ..

  $ hg init repo4
  $ cd repo4
  $ touch modified removed deleted
432
  $ hg ci -q -A -m 'initial checkin'
Nicolas Dumazet's avatar
Nicolas Dumazet committed
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
  $ touch added unknown
  $ hg add added
  $ hg remove removed
  $ rm deleted
  $ echo x > modified
  $ hg copy modified copied
  $ hg ci -m 'test checkin' -d "1000001 0"
  $ rm *
  $ touch unrelated
  $ hg ci -q -A -m 'unrelated checkin' -d "1000002 0"

hg status --change 1:

  $ hg status --change 1
  M modified
  A added
  A copied
  R removed

hg status --change 1 unrelated:

  $ hg status --change 1 unrelated

hg status -C --change 1 added modified copied removed deleted:

  $ hg status -C --change 1 added modified copied removed deleted
  M modified
  A added
  A copied
    modified
  R removed

465
hg status -A --change 1 and revset:
Nicolas Dumazet's avatar
Nicolas Dumazet committed
466

467
  $ hg status -A --change '1|1'
Nicolas Dumazet's avatar
Nicolas Dumazet committed
468
469
470
471
472
473
  M modified
  A added
  A copied
    modified
  R removed
  C deleted
474
475
476

  $ cd ..

477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
hg status with --rev and reverted changes:

  $ hg init reverted-changes-repo
  $ cd reverted-changes-repo
  $ echo a > file
  $ hg add file
  $ hg ci -m a
  $ echo b > file
  $ hg ci -m b

reverted file should appear clean

  $ hg revert -r 0 .
  reverting file
  $ hg status -A --rev 0
  C file

#if execbit
reverted file with changed flag should appear modified

  $ chmod +x file
  $ hg status -A --rev 0
  M file

501
502
  $ hg revert -r 0 .
  reverting file
503
504
505
506
507
508
509
510
511
512
513

reverted and committed file with changed flag should appear modified

  $ hg co -C .
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ chmod +x file
  $ hg ci -m 'change flag'
  $ hg status -A --rev 1 --rev 2
  M file
  $ hg diff -r 1 -r 2

514
515
#endif

516
517
  $ cd ..

518
519
520
521
hg status of binary file starting with '\1\n', a separator for metadata:

  $ hg init repo5
  $ cd repo5
522
  >>> open("010a", r"wb").write(b"\1\nfoo") and None
523
524
525
526
  $ hg ci -q -A -m 'initial checkin'
  $ hg status -A
  C 010a

527
  >>> open("010a", r"wb").write(b"\1\nbar") and None
528
529
530
531
532
533
534
535
536
537
  $ hg status -A
  M 010a
  $ hg ci -q -m 'modify 010a'
  $ hg status -A --rev 0:1
  M 010a

  $ touch empty
  $ hg ci -q -A -m 'add another file'
  $ hg status -A --rev 1:2 010a
  C 010a
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

  $ cd ..

test "hg status" with "directory pattern" which matches against files
only known on target revision.

  $ hg init repo6
  $ cd repo6

  $ echo a > a.txt
  $ hg add a.txt
  $ hg commit -m '#0'
  $ mkdir -p 1/2/3/4/5
  $ echo b > 1/2/3/4/5/b.txt
  $ hg add 1/2/3/4/5/b.txt
  $ hg commit -m '#1'

  $ hg update -C 0 > /dev/null
  $ hg status -A
  C a.txt

the directory matching against specified pattern should be removed,
because directory existence prevents 'dirstate.walk()' from showing
warning message about such pattern.

  $ test ! -d 1
  $ hg status -A --rev 1 1/2/3/4/5/b.txt
  R 1/2/3/4/5/b.txt
  $ hg status -A --rev 1 1/2/3/4/5
  R 1/2/3/4/5/b.txt
  $ hg status -A --rev 1 1/2/3
  R 1/2/3/4/5/b.txt
  $ hg status -A --rev 1 1
  R 1/2/3/4/5/b.txt

573
574
  $ hg status --config ui.formatdebug=True --rev 1 1
  status = [
575
      {
576
          'itemtype': 'file',
577
578
579
          'path': '1/2/3/4/5/b.txt',
          'status': 'R'
      },
580
581
  ]

582
583
584
585
586
#if windows
  $ hg --config ui.slash=false status -A --rev 1 1
  R 1\2\3\4\5\b.txt
#endif

587
  $ cd ..
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624

Status after move overwriting a file (issue4458)
=================================================


  $ hg init issue4458
  $ cd issue4458
  $ echo a > a
  $ echo b > b
  $ hg commit -Am base
  adding a
  adding b


with --force

  $ hg mv b --force a
  $ hg st --copies
  M a
    b
  R b
  $ hg revert --all
  reverting a
  undeleting b
  $ rm *.orig

without force

  $ hg rm a
  $ hg st --copies
  R a
  $ hg mv b a
  $ hg st --copies
  M a
    b
  R b

625
626
627
628
629
630
631
632
using ui.statuscopies setting
  $ hg st --config ui.statuscopies=true
  M a
    b
  R b
  $ hg st --config ui.statuscopies=false
  M a
  R b
633
634
635
636
  $ hg st --config ui.tweakdefaults=yes
  M a
    b
  R b
637

638
639
640
641
642
643
644
645
646
647
648
using log status template (issue5155)
  $ hg log -Tstatus -r 'wdir()' -C
  changeset:   2147483647:ffffffffffff
  parent:      0:8c55c58b4c0e
  user:        test
  date:        * (glob)
  files:
  M a
    b
  R b
  
649
650
651
652
653
654
655
  $ hg log -GTstatus -r 'wdir()' -C
  o  changeset:   2147483647:ffffffffffff
  |  parent:      0:8c55c58b4c0e
  ~  user:        test
     date:        * (glob)
     files:
     M a
656
       b
657
658
     R b
  
659

660
661
662
663
664
665
666
667
Other "bug" highlight, the revision status does not report the copy information.
This is buggy behavior.

  $ hg commit -m 'blah'
  $ hg st --copies --change .
  M a
  R b

668
669
670
671
672
673
674
675
676
677
678
679
680
using log status template, the copy information is displayed correctly.
  $ hg log -Tstatus -r. -C
  changeset:   1:6685fde43d21
  tag:         tip
  user:        test
  date:        * (glob)
  summary:     blah
  files:
  M a
    b
  R b
  

681
  $ cd ..
682
683
684
685
686
687
688
689

Make sure .hg doesn't show up even as a symlink

  $ hg init repo0
  $ mkdir symlink-repo0
  $ cd symlink-repo0
  $ ln -s ../repo0/.hg
  $ hg status
690

691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
If the size hasn’t changed but mtime has, status needs to read the contents
of the file to check whether it has changed

  $ echo 1 > a
  $ echo 1 > b
  $ touch -t 200102030000 a b
  $ hg commit -Aqm '#0'
  $ echo 2 > a
  $ touch -t 200102040000 a b
  $ hg status
  M a

Asking specifically for the status of a deleted/removed file

  $ rm a
  $ rm b
  $ hg status a
  ! a
  $ hg rm a
  $ hg rm b
  $ hg status a
  R a
713
714
715
  $ hg commit -qm '#1'
  $ hg status a
  a: $ENOENT$
716

717
718
719
720
721
722
723
724
725
726
Check using include flag with pattern when status does not need to traverse
the working directory (issue6483)

  $ cd ..
  $ hg init issue6483
  $ cd issue6483
  $ touch a.py b.rs
  $ hg add a.py b.rs
  $ hg st -aI "*.py"
  A a.py
727

728
729
730
731
732
Also check exclude pattern

  $ hg st -aX "*.rs"
  A a.py

733
734
735
736
737
738
issue6335
When a directory containing a tracked file gets symlinked, as of 5.8
`hg st` only gives the correct answer about clean (or deleted) files
if also listing unknowns.
The tree-based dirstate and status algorithm fix this:

739
#if symlink no-dirstate-v1 rust
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754

  $ cd ..
  $ hg init issue6335
  $ cd issue6335
  $ mkdir foo
  $ touch foo/a
  $ hg ci -Ama
  adding foo/a
  $ mv foo bar
  $ ln -s bar foo
  $ hg status
  ! foo/a
  ? bar/a
  ? foo

755
  $ hg status -c  # incorrect output without the Rust implementation
756
757
758
  $ hg status -cu
  ? bar/a
  ? foo
759
  $ hg status -d  # incorrect output without the Rust implementation
760
761
762
763
764
765
766
  ! foo/a
  $ hg status -du
  ! foo/a
  ? bar/a
  ? foo

#endif
Simon Sapin's avatar
Simon Sapin committed
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826


Create a repo with files in each possible status

  $ cd ..
  $ hg init repo7
  $ cd repo7
  $ mkdir subdir
  $ touch clean modified deleted removed
  $ touch subdir/clean subdir/modified subdir/deleted subdir/removed
  $ echo ignored > .hgignore
  $ hg ci -Aqm '#0'
  $ echo 1 > modified
  $ echo 1 > subdir/modified
  $ rm deleted
  $ rm subdir/deleted
  $ hg rm removed
  $ hg rm subdir/removed
  $ touch unknown ignored
  $ touch subdir/unknown subdir/ignored

Check the output

  $ hg status
  M modified
  M subdir/modified
  R removed
  R subdir/removed
  ! deleted
  ! subdir/deleted
  ? subdir/unknown
  ? unknown

  $ hg status -mard
  M modified
  M subdir/modified
  R removed
  R subdir/removed
  ! deleted
  ! subdir/deleted

  $ hg status -A
  M modified
  M subdir/modified
  R removed
  R subdir/removed
  ! deleted
  ! subdir/deleted
  ? subdir/unknown
  ? unknown
  I ignored
  I subdir/ignored
  C .hgignore
  C clean
  C subdir/clean

Note: `hg status some-name` creates a patternmatcher which is not supported
yet by the Rust implementation of status, but includematcher is supported.
--include is used below for that reason

827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
#if unix-permissions

Not having permission to read a directory that contains tracked files makes
status emit a warning then behave as if the directory was empty or removed
entirely:

  $ chmod 0 subdir
  $ hg status --include subdir
  subdir: Permission denied
  R subdir/removed
  ! subdir/clean
  ! subdir/deleted
  ! subdir/modified
  $ chmod 755 subdir

#endif

Simon Sapin's avatar
Simon Sapin committed
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
Remove a directory that contains tracked files

  $ rm -r subdir
  $ hg status --include subdir
  R subdir/removed
  ! subdir/clean
  ! subdir/deleted
  ! subdir/modified

 and replace it by a file

  $ touch subdir
  $ hg status --include subdir
  R subdir/removed
  ! subdir/clean
  ! subdir/deleted
  ! subdir/modified
  ? subdir

Replaced a deleted or removed file with a directory

  $ mkdir deleted removed
  $ touch deleted/1 removed/1
  $ hg status --include deleted --include removed
  R removed
  ! deleted
  ? deleted/1
  ? removed/1
  $ hg add removed/1
  $ hg status --include deleted --include removed
  A removed/1
  R removed
  ! deleted
  ? deleted/1

Deeply nested files in an ignored directory are still listed on request

  $ echo ignored-dir >> .hgignore
  $ mkdir ignored-dir
  $ mkdir ignored-dir/subdir
  $ touch ignored-dir/subdir/1
  $ hg status --ignored
  I ignored
  I ignored-dir/subdir/1
Matt Harbison's avatar
Matt Harbison committed
888

889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
Check using include flag while listing ignored composes correctly (issue6514)

  $ cd ..
  $ hg init issue6514
  $ cd issue6514
  $ mkdir ignored-folder
  $ touch A.hs B.hs C.hs ignored-folder/other.txt ignored-folder/ctest.hs
  $ cat >.hgignore <<EOF
  > A.hs
  > B.hs
  > ignored-folder/
  > EOF
  $ hg st -i -I 're:.*\.hs$'
  I A.hs
  I B.hs
  I ignored-folder/ctest.hs
905

906
#if rust dirstate-v2
907
908
909
910
911
912
913
914
915
916
917
918

Check read_dir caching

  $ cd ..
  $ hg init repo8
  $ cd repo8
  $ mkdir subdir
  $ touch subdir/a subdir/b
  $ hg ci -Aqm '#0'

The cached mtime is initially unset

919
920
  $ hg debugdirstate --all --no-dates | grep '^ '
      0         -1 unset               subdir
921
922
923
924
925
926

It is still not set when there are unknown files

  $ touch subdir/unknown
  $ hg status
  ? subdir/unknown
927
928
  $ hg debugdirstate --all --no-dates | grep '^ '
      0         -1 unset               subdir
929
930
931
932
933

Now the directory is eligible for caching, so its mtime is save in the dirstate

  $ rm subdir/unknown
  $ hg status
934
935
  $ hg debugdirstate --all --no-dates | grep '^ '
      0         -1 set                 subdir
936
937
938
939
940
941
942
943
944
945
946

This time the command should be ever so slightly faster since it does not need `read_dir("subdir")`

  $ hg status

Creating a new file changes the directorys mtime, invalidating the cache

  $ touch subdir/unknown
  $ hg status
  ? subdir/unknown

947
948
949
950
951
952
  $ rm subdir/unknown
  $ hg status

Removing a node from the dirstate resets the cache for its parent directory

  $ hg forget subdir/a
953
954
  $ hg debugdirstate --all --no-dates | grep '^ '
      0         -1 set                 subdir
955
  $ hg ci -qm '#1'
956
957
  $ hg debugdirstate --all --no-dates | grep '^ '
      0         -1 unset               subdir
958
959
960
  $ hg status
  ? subdir/a

961
#endif