@@ -1127,3 +1127,202 @@ pub fn checkout_commit(commit_hash: String) -> anyhow::Result<()> {
11271127 restore_working_tree ( commit_hash) ?;
11281128 Ok ( ( ) )
11291129}
1130+
1131+ #[ cfg( test) ]
1132+ mod tests {
1133+ use super :: * ;
1134+ use std:: fs;
1135+
1136+ fn setup_test_repo ( ) {
1137+ let _ = fs:: remove_dir_all ( ".aggit" ) ;
1138+ init ( PathBuf :: from ( "." ) ) . unwrap ( ) ;
1139+ }
1140+
1141+ fn cleanup_test_repo ( ) {
1142+ let _ = fs:: remove_dir_all ( ".aggit" ) ;
1143+ }
1144+
1145+ #[ test]
1146+ #[ serial_test:: serial]
1147+ fn test_init_creates_directories ( ) {
1148+ cleanup_test_repo ( ) ;
1149+ let repo = PathBuf :: from ( ".aggit_test_repo" ) ;
1150+ let _ = fs:: remove_dir_all ( & repo) ;
1151+ init ( repo. clone ( ) ) . unwrap ( ) ;
1152+ assert ! ( repo. join( ".aggit" ) . exists( ) ) ;
1153+ assert ! ( repo. join( ".aggit/objects" ) . exists( ) ) ;
1154+ assert ! ( repo. join( ".aggit/refs/heads" ) . exists( ) ) ;
1155+ assert ! ( repo. join( ".aggit/refs/index" ) . exists( ) ) ;
1156+ let head = fs:: read_to_string ( repo. join ( ".aggit/HEAD" ) ) . unwrap ( ) ;
1157+ assert_eq ! ( head, "ref: refs/heads/main" ) ;
1158+ let _ = fs:: remove_dir_all ( & repo) ;
1159+ }
1160+
1161+ #[ test]
1162+ #[ serial_test:: serial]
1163+ fn test_hash_object_without_write ( ) {
1164+ cleanup_test_repo ( ) ;
1165+ setup_test_repo ( ) ;
1166+ let mut data = b"hello world" . to_vec ( ) ;
1167+ let hash = hash_object ( & mut data, ObjectType :: Blob , false ) . unwrap ( ) ;
1168+ assert_eq ! ( hash. len( ) , 40 ) ;
1169+ let path = PathBuf :: from ( ".aggit/objects" )
1170+ . join ( & hash[ ..2 ] )
1171+ . join ( & hash[ 2 ..] ) ;
1172+ assert ! ( !path. exists( ) ) ;
1173+ cleanup_test_repo ( ) ;
1174+ }
1175+
1176+ #[ test]
1177+ #[ serial_test:: serial]
1178+ fn test_hash_object_with_write ( ) {
1179+ cleanup_test_repo ( ) ;
1180+ setup_test_repo ( ) ;
1181+ let mut data = b"hello world" . to_vec ( ) ;
1182+ let hash = hash_object ( & mut data, ObjectType :: Blob , true ) . unwrap ( ) ;
1183+ let path = PathBuf :: from ( ".aggit/objects" )
1184+ . join ( & hash[ ..2 ] )
1185+ . join ( & hash[ 2 ..] ) ;
1186+ assert ! ( path. exists( ) ) ;
1187+ cleanup_test_repo ( ) ;
1188+ }
1189+
1190+ #[ test]
1191+ #[ serial_test:: serial]
1192+ fn test_find_object_success ( ) {
1193+ cleanup_test_repo ( ) ;
1194+ setup_test_repo ( ) ;
1195+ let mut data = b"find me" . to_vec ( ) ;
1196+ let hash = hash_object ( & mut data, ObjectType :: Blob , true ) . unwrap ( ) ;
1197+ let found = find_object ( & hash) . unwrap ( ) ;
1198+ assert ! ( found. to_string_lossy( ) . contains( & hash[ ..2 ] ) ) ;
1199+ cleanup_test_repo ( ) ;
1200+ }
1201+
1202+ #[ test]
1203+ #[ serial_test:: serial]
1204+ fn test_find_object_not_found ( ) {
1205+ cleanup_test_repo ( ) ;
1206+ setup_test_repo ( ) ;
1207+ let result = find_object ( "0000000000000000000000000000000000000000" ) ;
1208+ assert ! ( result. is_err( ) ) ;
1209+ cleanup_test_repo ( ) ;
1210+ }
1211+
1212+ #[ test]
1213+ fn test_read_object_roundtrip ( ) {
1214+ let data = b"roundtrip data" . to_vec ( ) ;
1215+ let hash = hash_object ( & mut data. clone ( ) , ObjectType :: Blob , true ) . unwrap ( ) ;
1216+ let ( obj_type, read_data) = read_object ( & hash) . unwrap ( ) ;
1217+ assert_eq ! ( obj_type, ObjectType :: Blob ) ;
1218+ assert_eq ! ( read_data, b"roundtrip data" ) ;
1219+ }
1220+
1221+ #[ test]
1222+ #[ serial_test:: serial]
1223+ fn test_get_current_branch ( ) {
1224+ cleanup_test_repo ( ) ;
1225+ setup_test_repo ( ) ;
1226+ let branch = get_current_branch ( ) . unwrap ( ) ;
1227+ assert_eq ! ( branch, "main" ) ;
1228+ cleanup_test_repo ( ) ;
1229+ }
1230+
1231+ #[ test]
1232+ fn test_index_path_for_branch ( ) {
1233+ let path = index_path_for_branch ( "main" ) ;
1234+ assert_eq ! ( path, PathBuf :: from( ".aggit/refs/index/main" ) ) ;
1235+ }
1236+
1237+ #[ test]
1238+ fn test_head_path_for_branch ( ) {
1239+ let path = head_path_for_branch ( "main" ) ;
1240+ assert_eq ! ( path, PathBuf :: from( ".aggit/refs/heads/main" ) ) ;
1241+ }
1242+
1243+ #[ test]
1244+ fn test_object_type_from_str ( ) {
1245+ assert_eq ! ( ObjectType :: from_str( "blob" ) . unwrap( ) , ObjectType :: Blob ) ;
1246+ assert_eq ! ( ObjectType :: from_str( "commit" ) . unwrap( ) , ObjectType :: Commit ) ;
1247+ assert_eq ! ( ObjectType :: from_str( "tree" ) . unwrap( ) , ObjectType :: Tree ) ;
1248+ assert ! ( ObjectType :: from_str( "unknown" ) . is_err( ) ) ;
1249+ }
1250+
1251+ #[ test]
1252+ fn test_cat_file_mode_from_str ( ) {
1253+ assert ! ( CatFileMode :: from_str( "blob" ) . is_ok( ) ) ;
1254+ assert ! ( CatFileMode :: from_str( "size" ) . is_ok( ) ) ;
1255+ assert ! ( CatFileMode :: from_str( "type" ) . is_ok( ) ) ;
1256+ assert ! ( CatFileMode :: from_str( "pretty" ) . is_ok( ) ) ;
1257+ assert ! ( CatFileMode :: from_str( "invalid" ) . is_err( ) ) ;
1258+ }
1259+
1260+ #[ test]
1261+ #[ serial_test:: serial]
1262+ fn test_write_and_read_index ( ) {
1263+ cleanup_test_repo ( ) ;
1264+ setup_test_repo ( ) ;
1265+ let entries = vec ! [ IndexEntry {
1266+ ctime_s: 0 ,
1267+ ctime_n: 0 ,
1268+ mtime_s: 0 ,
1269+ mtime_n: 0 ,
1270+ dev: 0 ,
1271+ ino: 0 ,
1272+ mode: 0o100644 ,
1273+ uid: 0 ,
1274+ gid: 0 ,
1275+ size: 5 ,
1276+ sha1: [ 0u8 ; 20 ] ,
1277+ flags: 4 ,
1278+ path: "test.txt" . to_string( ) ,
1279+ } ] ;
1280+ write_index ( & entries) . unwrap ( ) ;
1281+ let read = read_index ( ) . unwrap ( ) ;
1282+ assert_eq ! ( read. len( ) , 1 ) ;
1283+ assert_eq ! ( read[ 0 ] . path, "test.txt" ) ;
1284+ cleanup_test_repo ( ) ;
1285+ }
1286+
1287+ #[ test]
1288+ fn test_read_tree_with_data ( ) {
1289+ let mut tree_data = Vec :: new ( ) ;
1290+ tree_data. extend_from_slice ( b"100644 file.txt\x00 " ) ;
1291+ tree_data. extend_from_slice ( & [ 0u8 ; 20 ] ) ;
1292+ let entries = read_tree ( None , Some ( tree_data) ) . unwrap ( ) ;
1293+ assert_eq ! ( entries. len( ) , 1 ) ;
1294+ assert_eq ! ( entries[ 0 ] . 1 , "file.txt" ) ;
1295+ }
1296+
1297+ #[ test]
1298+ #[ serial_test:: serial]
1299+ fn test_get_local_current_hash_no_commits ( ) {
1300+ cleanup_test_repo ( ) ;
1301+ setup_test_repo ( ) ;
1302+ let ( hash, branch) = get_local_current_hash ( ) . unwrap ( ) ;
1303+ assert ! ( hash. is_none( ) ) ;
1304+ assert_eq ! ( branch, "main" ) ;
1305+ cleanup_test_repo ( ) ;
1306+ }
1307+
1308+ #[ test]
1309+ #[ serial_test:: serial]
1310+ fn test_list_branches_no_error ( ) {
1311+ cleanup_test_repo ( ) ;
1312+ setup_test_repo ( ) ;
1313+ list_branches ( ) . unwrap ( ) ;
1314+ cleanup_test_repo ( ) ;
1315+ }
1316+
1317+ #[ test]
1318+ #[ serial_test:: serial]
1319+ fn test_collect_reachable_objects_blob_only ( ) {
1320+ cleanup_test_repo ( ) ;
1321+ setup_test_repo ( ) ;
1322+ let mut data = b"blob content" . to_vec ( ) ;
1323+ let hash = hash_object ( & mut data, ObjectType :: Blob , true ) . unwrap ( ) ;
1324+ let objects = collect_reachable_objects ( & hash, None ) . unwrap ( ) ;
1325+ assert ! ( objects. contains( & hash) ) ;
1326+ cleanup_test_repo ( ) ;
1327+ }
1328+ }
0 commit comments