diff options
| author | Sadeep Madurange <sadeep@asciimx.com> | 2026-04-04 11:55:08 +0800 |
|---|---|---|
| committer | Sadeep Madurange <sadeep@asciimx.com> | 2026-04-04 14:52:02 +0800 |
| commit | cf421aeff4faa15a2a80495345ae76023830ca86 (patch) | |
| tree | d417dd85f75fc4c532bb0954ed59bea87d350914 /vcx | |
| parent | 3af329abee56900dd42cb305bd7a431ab3ded90a (diff) | |
| download | cvn-cf421aeff4faa15a2a80495345ae76023830ca86.tar.gz | |
Unit tests and fix hash collisions, deletions.
Diffstat (limited to 'vcx')
| -rw-r--r-- | vcx | 42 |
1 files changed, 32 insertions, 10 deletions
@@ -2,7 +2,6 @@ use strict; use warnings; - use File::Path qw(make_path); use File::Copy qw(copy); use File::Find; @@ -15,9 +14,9 @@ use Digest::SHA qw(sha1_hex); use POSIX qw(strftime); use constant VCX_DIR => '.vcx'; -use constant HEAD => VCX_DIR . '/head'; # Current commit ID -use constant OBJ_DIR => VCX_DIR . '/objs'; # Latest version of a file -use constant REV_DIR => VCX_DIR . '/revs'; # Commits +use constant HEAD => VCX_DIR . '/head'; # Current commit ID +use constant OBJ_DIR => VCX_DIR . '/obj'; # Latest version of a file +use constant REV_DIR => VCX_DIR . '/rev'; # Commits # Staging area use constant TMP_DIR => VCX_DIR . '/index'; @@ -160,10 +159,10 @@ sub run_add { my $next_id_hex = to_hex_id(from_hex_id($head) + 1); - my @entries; + my %entries; open my $afh, '>>', TMP_META_FILE or die $!; - init_stage($latest_tree_dir, \@entries); + init_stage($latest_tree_dir, \%entries); foreach my $input (@targets) { my @expanded = bsd_glob($input); @@ -178,7 +177,7 @@ sub run_add { return if -d $_; my $rel = $File::Find::name =~ s|^\./||r; - push @entries, $rel; + $entries{$rel} = 1; my $staged_path = File::Spec->catfile(TMP_TREE, $rel); my $prev_link = File::Spec->catfile($latest_tree_dir, $rel); @@ -197,7 +196,7 @@ sub run_add { my $obj_path = File::Spec->catfile(OBJ_DIR, $obj_name); if (-e $obj_path) { - my $p_path = File::Spec->catfile(TMP_DIFF, "$obj_name.$next_id_hex.patch"); + my $p_path = File::Spec->catfile(TMP_DIFF, "$obj_name.patch"); if (-T $_) { if (compare($_, $obj_path) != 0) { unless (-d TMP_DIFF) { make_path(TMP_DIFF); } @@ -231,9 +230,32 @@ sub run_add { }, $t); } } + + # Pass 2: History -> Workspace (Detects Deletions) + foreach my $path (keys %entries) { + if (!-e $path && !-l $path) { + delete $entries{$path}; + my $staged_path = File::Spec->catfile(TMP_TREE, $path); + if (-e $staged_path || -l $staged_path) { + unlink($staged_path) or die "Could not unlink staged $path: $!"; + my $parent = dirname($staged_path); + while ($parent ne TMP_TREE && -d $parent) { + last if bsd_glob("$parent/*"); # Stop if not empty + rmdir($parent); + $parent = dirname($parent); + } + } + print "[D] $path (staged for deletion)\n"; + } + } + close $afh; - my $tree_data = join("\n", sort @entries); + my @sorted_paths = sort keys %entries; + my $tree_ents = join("\n", @sorted_paths); + my $tree_header = "tree " . scalar(@sorted_paths) . "\n"; + my $tree_data = $tree_header . $tree_ents; + my $tree_hash = sha1_hex($tree_data); my $tree_file = File::Spec->catfile(TMP_DIR, "tree-$tree_hash"); open my $fh, '>', $tree_file or die $!; close $fh; @@ -514,7 +536,7 @@ sub init_stage { my $target = readlink($_); symlink($target, $staged_path) or die "Failed to link $rel: $!"; - push @$entries_ref, $rel; + $entries_ref->{$rel} = 1; }, no_chdir => 1 }, $latest_tree_dir); |
