@@ -1536,6 +1536,218 @@ func TestGit(t *testing.T) {
1536
1536
)
1537
1537
}
1538
1538
1539
+ func TestJujutsu (t * testing.T ) {
1540
+ as := require .New (t )
1541
+
1542
+ test .SetenvXdgConfigDir (t )
1543
+ tempDir := test .TempExamples (t )
1544
+ configPath := filepath .Join (tempDir , "/treefmt.toml" )
1545
+
1546
+ test .ChangeWorkDir (t , tempDir )
1547
+
1548
+ // basic config
1549
+ cfg := & config.Config {
1550
+ FormatterConfigs : map [string ]* config.Formatter {
1551
+ "echo" : {
1552
+ Command : "echo" , // will not generate any underlying changes in the file
1553
+ Includes : []string {"*" },
1554
+ },
1555
+ },
1556
+ }
1557
+
1558
+ test .WriteConfig (t , configPath , cfg )
1559
+
1560
+ // init a jujutsu repo
1561
+ jjCmd := exec .Command ("jj" , "git" , "init" )
1562
+ as .NoError (jjCmd .Run (), "failed to init jujutsu repository" )
1563
+
1564
+ // run treefmt before adding anything to the jj index
1565
+ // Jujutsu depends on updating the index with a `jj` command. So, until we do
1566
+ // that, the treefmt should return nothing, since the walker is executed with
1567
+ // `--ignore-working-copy` which does not update the index.
1568
+ treefmt (t ,
1569
+ withConfig (configPath , cfg ),
1570
+ withNoError (t ),
1571
+ withStats (t , map [stats.Type ]int {
1572
+ stats .Traversed : 0 ,
1573
+ stats .Matched : 0 ,
1574
+ stats .Formatted : 0 ,
1575
+ stats .Changed : 0 ,
1576
+ }),
1577
+ )
1578
+
1579
+ // update jujutsu's index
1580
+ jjCmd = exec .Command ("jj" )
1581
+ as .NoError (jjCmd .Run (), "failed to update the index" )
1582
+
1583
+ // This is our first pass, since previously the files were not in the index. This should format all files.
1584
+ treefmt (t ,
1585
+ withConfig (configPath , cfg ),
1586
+ withNoError (t ),
1587
+ withStats (t , map [stats.Type ]int {
1588
+ stats .Traversed : 32 ,
1589
+ stats .Matched : 32 ,
1590
+ stats .Formatted : 32 ,
1591
+ stats .Changed : 0 ,
1592
+ }),
1593
+ )
1594
+
1595
+ // create a file which should be in .gitignore
1596
+ f , err := os .CreateTemp (tempDir , "test-*.txt" )
1597
+ as .NoError (err , "failed to create temp file" )
1598
+
1599
+ // update jujutsu's index
1600
+ jjCmd = exec .Command ("jj" )
1601
+ as .NoError (jjCmd .Run (), "failed to update the index" )
1602
+
1603
+ t .Cleanup (func () {
1604
+ _ = f .Close ()
1605
+ })
1606
+
1607
+ treefmt (t ,
1608
+ withConfig (configPath , cfg ),
1609
+ withNoError (t ),
1610
+ withStats (t , map [stats.Type ]int {
1611
+ stats .Traversed : 32 ,
1612
+ stats .Matched : 32 ,
1613
+ stats .Formatted : 0 ,
1614
+ stats .Changed : 0 ,
1615
+ }),
1616
+ )
1617
+
1618
+ // remove python directory
1619
+ as .NoError (os .RemoveAll (filepath .Join (tempDir , "python" )), "failed to remove python directory" )
1620
+
1621
+ // update jujutsu's index
1622
+ jjCmd = exec .Command ("jj" )
1623
+ as .NoError (jjCmd .Run (), "failed to update the index" )
1624
+
1625
+ // we should traverse and match against fewer files, but no formatting should occur as no formatting signatures
1626
+ // are impacted
1627
+ treefmt (t ,
1628
+ withConfig (configPath , cfg ),
1629
+ withNoError (t ),
1630
+ withStats (t , map [stats.Type ]int {
1631
+ stats .Traversed : 29 ,
1632
+ stats .Matched : 29 ,
1633
+ stats .Formatted : 0 ,
1634
+ stats .Changed : 0 ,
1635
+ }),
1636
+ )
1637
+
1638
+ // remove nixpkgs.toml from the filesystem but leave it in the index
1639
+ as .NoError (os .Remove (filepath .Join (tempDir , "nixpkgs.toml" )))
1640
+
1641
+ // walk with filesystem instead of with jujutsu
1642
+ // the .jj folder contains 100 additional files
1643
+ // when added to the 30 we started with (34 minus nixpkgs.toml which we removed from the filesystem), we should
1644
+ // traverse 130 files.
1645
+ treefmt (t ,
1646
+ withArgs ("--walk" , "filesystem" ),
1647
+ withConfig (configPath , cfg ),
1648
+ withNoError (t ),
1649
+ withStats (t , map [stats.Type ]int {
1650
+ stats .Traversed : 130 ,
1651
+ stats .Matched : 130 ,
1652
+ stats .Formatted : 102 , // the echo formatter should only be applied to the new files
1653
+ stats .Changed : 0 ,
1654
+ }),
1655
+ )
1656
+
1657
+ // format specific sub paths
1658
+ // we should traverse and match against those files, but without any underlying change to their files or their
1659
+ // formatting config, we will not format them
1660
+
1661
+ treefmt (t ,
1662
+ withArgs ("go" ),
1663
+ withConfig (configPath , cfg ),
1664
+ withNoError (t ),
1665
+ withStats (t , map [stats.Type ]int {
1666
+ stats .Traversed : 2 ,
1667
+ stats .Matched : 2 ,
1668
+ stats .Formatted : 0 ,
1669
+ stats .Changed : 0 ,
1670
+ }),
1671
+ )
1672
+
1673
+ treefmt (t ,
1674
+ withArgs ("go" , "haskell" ),
1675
+ withConfig (configPath , cfg ),
1676
+ withNoError (t ),
1677
+ withStats (t , map [stats.Type ]int {
1678
+ stats .Traversed : 9 ,
1679
+ stats .Matched : 9 ,
1680
+ stats .Formatted : 0 ,
1681
+ stats .Changed : 0 ,
1682
+ }),
1683
+ )
1684
+
1685
+ treefmt (t ,
1686
+ withArgs ("-C" , tempDir , "go" , "haskell" , "ruby" ),
1687
+ withConfig (configPath , cfg ),
1688
+ withNoError (t ),
1689
+ withStats (t , map [stats.Type ]int {
1690
+ stats .Traversed : 10 ,
1691
+ stats .Matched : 10 ,
1692
+ stats .Formatted : 0 ,
1693
+ stats .Changed : 0 ,
1694
+ }),
1695
+ )
1696
+
1697
+ // try with a bad path
1698
+ treefmt (t ,
1699
+ withArgs ("-C" , tempDir , "haskell" , "foo" ),
1700
+ withConfig (configPath , cfg ),
1701
+ withError (func (as * require.Assertions , err error ) {
1702
+ as .ErrorContains (err , "foo not found" )
1703
+ }),
1704
+ )
1705
+
1706
+ // try with a path not in the jj index
1707
+ _ , err = os .Create (filepath .Join (tempDir , "foo.txt" ))
1708
+ as .NoError (err )
1709
+
1710
+ // update jujutsu's index
1711
+ jjCmd = exec .Command ("jj" )
1712
+ as .NoError (jjCmd .Run (), "failed to update the index" )
1713
+
1714
+ treefmt (t ,
1715
+ withArgs ("haskell" , "foo.txt" , "-vv" ),
1716
+ withConfig (configPath , cfg ),
1717
+ withNoError (t ),
1718
+ withStats (t , map [stats.Type ]int {
1719
+ stats .Traversed : 8 ,
1720
+ stats .Matched : 8 ,
1721
+ stats .Formatted : 1 , // we only format foo.txt, which is new to the cache
1722
+ stats .Changed : 0 ,
1723
+ }),
1724
+ )
1725
+
1726
+ treefmt (t ,
1727
+ withArgs ("go" , "foo.txt" ),
1728
+ withConfig (configPath , cfg ),
1729
+ withNoError (t ),
1730
+ withStats (t , map [stats.Type ]int {
1731
+ stats .Traversed : 3 ,
1732
+ stats .Matched : 3 ,
1733
+ stats .Formatted : 0 ,
1734
+ stats .Changed : 0 ,
1735
+ }),
1736
+ )
1737
+
1738
+ treefmt (t ,
1739
+ withArgs ("foo.txt" ),
1740
+ withConfig (configPath , cfg ),
1741
+ withNoError (t ),
1742
+ withStats (t , map [stats.Type ]int {
1743
+ stats .Traversed : 1 ,
1744
+ stats .Matched : 1 ,
1745
+ stats .Formatted : 0 ,
1746
+ stats .Changed : 0 ,
1747
+ }),
1748
+ )
1749
+ }
1750
+
1539
1751
func TestTreeRootCmd (t * testing.T ) {
1540
1752
as := require .New (t )
1541
1753
0 commit comments