7 use lib
$ENV{GL_LIBDIR
};
10 use Gitolite
::Conf
::Load
;
12 # gitolite command to lock and unlock (binary) files and deal with locks.
15 Usage: ssh git@host lock -l <repo> <file> # lock a file
16 ssh git@host lock -u <repo> <file> # unlock a file
17 ssh git@host lock --break <repo> <file> # break someone else's lock
18 ssh git@host lock -ls <repo> # list locked files for repo
20 See doc/locking.mkd for other details.
23 usage
() if not @ARGV or $ARGV[0] eq '-h';
24 $ENV{GL_USER
} or _die
"GL_USER not set";
27 $op = 'lock' if $ARGV[0] eq '-l';
28 $op = 'unlock' if $ARGV[0] eq '-u';
29 $op = 'break' if $ARGV[0] eq '--break';
30 $op = 'list' if $ARGV[0] eq '-ls';
35 _die
"You are not authorised" if access
( $repo, $ENV{GL_USER
}, 'W', 'any' ) =~ /DENIED/;
36 _die
"You are not authorised" if $op eq 'break' and access
( $repo, $ENV{GL_USER
}, '+', 'any' ) =~ /DENIED/;
38 my $file = shift || '';
39 usage
() if $op ne 'list' and not $file;
41 _chdir
( $ENV{GL_REPO_BASE
} );
44 _die
"aborting, file '$file' not found in any branch" if $file and not object_exists
($file);
48 if ( $op eq 'lock' ) {
49 f_lock
( $repo, $file );
50 } elsif ( $op eq 'unlock' ) {
51 f_unlock
( $repo, $file );
52 } elsif ( $op eq 'break' ) {
53 f_break
( $repo, $file );
54 } elsif ( $op eq 'list' ) {
58 # ----------------------------------------------------------------------
59 # For a given path, return 1 if object exists in any branch, 0 if not.
60 # This is to prevent locking invalid objects.
65 my @branches = `git for-each-ref refs/heads '--format=%(refname)'`;
66 foreach my $b (@branches) {
68 system("git cat-file -e $b:$file 2>/dev/null") or return 1;
69 # note that with system(), the return value is "shell truth", so
70 # you check for success with "or", not "and"
72 return 0; # report object not found
75 # ----------------------------------------------------------------------
76 # everything below assumes we have already chdir'd to "$repo.git". Also, $ff
77 # is used as a global.
80 my ( $repo, $file ) = @_;
82 my %locks = get_locks
();
83 _die
"'$file' locked by '$locks{$file}{USER}' since " . localtime( $locks{$file}{TIME
} ) if $locks{$file}{USER
};
84 $locks{$file}{USER
} = $ENV{GL_USER
};
85 $locks{$file}{TIME
} = time;
90 my ( $repo, $file ) = @_;
92 my %locks = get_locks
();
93 _die
"'$file' not locked by '$ENV{GL_USER}'" if ( $locks{$file}{USER
} || '' ) ne $ENV{GL_USER
};
99 my ( $repo, $file ) = @_;
101 my %locks = get_locks
();
102 _die
"'$file' was not locked" unless $locks{$file};
103 push @
{ $locks{BREAKS
} }, time . " $ENV{GL_USER} $locks{$file}{USER} $locks{$file}{TIME} $file";
104 delete $locks{$file};
111 my %locks = get_locks
();
112 print "\n# locks held:\n\n";
113 map { print "$locks{$_}{USER}\t$_\t(" . scalar( localtime( $locks{$_}{TIME
} ) ) . ")\n" } grep { $_ ne 'BREAKS' } sort keys %locks;
114 print "\n# locks broken:\n\n";
115 for my $b ( @
{ $locks{BREAKS
} } ) {
116 my ( $when, $who, $whose, $how_old, $what ) = split ' ', $b;
117 print "$who\t$what\t(" . scalar( localtime($when) ) . ")\t(locked by $whose at " . scalar( localtime($how_old) ) . ")\n";
127 _die
"do '$ff' failed with '$@', contact your administrator" if $@
;
138 $Data::Dumper
::Indent
= 1;
139 $Data::Dumper
::Sortkeys
= 1;
141 my $dumped_data = Data
::Dumper
->Dump( [ \
%locks ], [qw(*locks)] );
142 _print
( $ff, $dumped_data );