#!/usr/bin/env perl use 5.10.1; use strict; use warnings; use autodie; use File::Basename 'dirname'; use File::Path 'make_path'; die "you must pass both a from and a to" unless @ARGV == 2; my ($from, $to) = @ARGV; die "you have changes in your working copy!" unless is_clean(); # move the real dir make_path(dirname($to)); safe_system('mv', $from, $to); # move the git dir (not really that important) make_path(dirname(".git/modules/$to")); safe_system('mv', ".git/modules/$from", ".git/modules/$to"); # update .gitmodules and .git/config book keeping spew($_, slurp($_) =~ s/\Q$from\E/$to/gr) for qw( .gitmodules .git/config ); my $dir_count = scalar split qr(/), $to =~ s(/$)()r; my $derp = ('../' x (2 + $dir_count)) . $to; # update .git/modules/$to/config book keeping spew( ".git/modules/$to/config", slurp(".git/modules/$to/config") =~ s/worktree.*/worktree = $derp/gr ); # update $to book keeping spew( "$to/.git", 'gitdir: ' . ('../' x $dir_count) . ".git/modules/$to" ); safe_system(qw( git add -A ), $from, $to, '.gitmodules' ); sub safe_system { system(@_); die "@_ exited poorly :(" if $? >> 8; } sub safe_capture { my $ret = qx(@_); die "@_ exited poorly :(" if $? >> 8; return $ret; } sub slurp { open my $fh, '<', $_[0]; local $/ = undef; scalar <$fh> } sub spew { open my $fh, '>', $_[0]; print {$fh} $_[1] } sub is_clean { !safe_capture(qw(git status --porcelain)) }