@@ -1544,19 +1544,21 @@ void test_diff_workdir__with_stale_index(void)
1544
1544
1545
1545
static int touch_file (void * payload , git_buf * path )
1546
1546
{
1547
- int fd ;
1548
- char b ;
1547
+ struct stat st ;
1548
+ struct timeval times [ 2 ] ;
1549
1549
1550
1550
GIT_UNUSED (payload );
1551
1551
if (git_path_isdir (path -> ptr ))
1552
1552
return 0 ;
1553
1553
1554
- cl_assert ((fd = p_open (path -> ptr , O_RDWR )) >= 0 );
1555
- cl_assert_equal_i (1 , p_read (fd , & b , 1 ));
1556
- cl_must_pass (p_lseek (fd , 0 , SEEK_SET ));
1557
- cl_must_pass (p_write (fd , & b , 1 ));
1558
- cl_must_pass (p_close (fd ));
1554
+ cl_must_pass (p_stat (path -> ptr , & st ));
1555
+
1556
+ times [0 ].tv_sec = st .st_mtime + 3 ;
1557
+ times [0 ].tv_usec = 0 ;
1558
+ times [1 ].tv_sec = st .st_mtime + 3 ;
1559
+ times [1 ].tv_usec = 0 ;
1559
1560
1561
+ cl_must_pass (p_utimes (path -> ptr , times ));
1560
1562
return 0 ;
1561
1563
}
1562
1564
@@ -1783,3 +1785,63 @@ void test_diff_workdir__to_index_conflicted(void) {
1783
1785
git_index_free (index );
1784
1786
git_tree_free (a );
1785
1787
}
1788
+
1789
+ void test_diff_workdir__only_writes_index_when_necessary (void )
1790
+ {
1791
+ git_index * index ;
1792
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT ;
1793
+ git_diff * diff = NULL ;
1794
+ git_diff_perfdata perf = GIT_DIFF_PERFDATA_INIT ;
1795
+ git_reference * head ;
1796
+ git_object * head_object ;
1797
+ git_oid initial , first , second ;
1798
+ git_buf path = GIT_BUF_INIT ;
1799
+ struct stat st ;
1800
+ struct timeval times [2 ];
1801
+
1802
+ opts .flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_UPDATE_INDEX ;
1803
+
1804
+ g_repo = cl_git_sandbox_init ("status" );
1805
+
1806
+ cl_git_pass (git_repository_index (& index , g_repo ));
1807
+ cl_git_pass (git_repository_head (& head , g_repo ));
1808
+ cl_git_pass (git_reference_peel (& head_object , head , GIT_OBJ_COMMIT ));
1809
+
1810
+ cl_git_pass (git_reset (g_repo , head_object , GIT_RESET_HARD , NULL ));
1811
+
1812
+ git_oid_cpy (& initial , git_index_checksum (index ));
1813
+
1814
+ /* update the index timestamp to avoid raciness */
1815
+ cl_must_pass (p_stat ("status/.git/index" , & st ));
1816
+
1817
+ times [0 ].tv_sec = st .st_mtime + 5 ;
1818
+ times [0 ].tv_usec = 0 ;
1819
+ times [1 ].tv_sec = st .st_mtime + 5 ;
1820
+ times [1 ].tv_usec = 0 ;
1821
+
1822
+ cl_must_pass (p_utimes ("status/.git/index" , times ));
1823
+
1824
+ /* ensure diff doesn't touch the index */
1825
+ cl_git_pass (git_diff_index_to_workdir (& diff , g_repo , NULL , & opts ));
1826
+ git_diff_free (diff );
1827
+
1828
+ git_oid_cpy (& first , git_index_checksum (index ));
1829
+ cl_assert (!git_oid_equal (& initial , & first ));
1830
+
1831
+ /* touch all the files so stat times are different */
1832
+ cl_git_pass (git_buf_sets (& path , "status" ));
1833
+ cl_git_pass (git_path_direach (& path , 0 , touch_file , NULL ));
1834
+
1835
+ cl_git_pass (git_diff_index_to_workdir (& diff , g_repo , NULL , & opts ));
1836
+ git_diff_free (diff );
1837
+
1838
+ /* ensure the second diff did update the index */
1839
+ git_oid_cpy (& second , git_index_checksum (index ));
1840
+ cl_assert (!git_oid_equal (& first , & second ));
1841
+
1842
+ git_buf_free (& path );
1843
+ git_object_free (head_object );
1844
+ git_reference_free (head );
1845
+ git_index_free (index );
1846
+ }
1847
+
0 commit comments