Newer Older
1754 lines | 41.295kb
renamed gitpub to gitprep
Yuki Kimoto authored on 2012-11-26
1
package Gitprep::Git;
copy gitweblite soruce code
root authored on 2012-11-23
2
use Mojo::Base -base;
3

            
4
use Carp 'croak';
cleanup
Yuki Kimoto authored on 2013-05-14
5
use Encode qw/encode decode/;
Supported specific character...
Tetsuya Hayashi authored on 2014-03-15
6
use Encode::Guess;
copy gitweblite soruce code
root authored on 2012-11-23
7
use Fcntl ':mode';
cleanup
Yuki Kimoto authored on 2013-05-14
8
use File::Basename qw/basename dirname/;
improved create repository f...
Yuki Kimoto authored on 2013-03-20
9
use File::Copy 'move';
cleanup
Yuki Kimoto authored on 2013-05-14
10
use File::Find 'find';
11
use File::Path qw/mkpath rmtree/;
add diff status bar to commi...
Yuki Kimoto authored on 2013-05-30
12
use POSIX 'floor';
fix bug that in CGI reposito...
Yuki Kimoto authored on 2015-11-05
13
use Gitprep::Util;
added create repository feat...
Yuki Kimoto authored on 2013-03-18
14

            
15
# Attributes
16
has 'bin';
Renamed encoding to default_...
Tetsuya Hayashi authored on 2014-03-15
17
has default_encoding => 'UTF-8';
cleanup blob page
Yuki Kimoto authored on 2013-03-19
18
has text_exts => sub { ['txt'] };
add time zone system
Yuki Kimoto authored on 2014-03-08
19
has 'time_zone_second';
cleanup encoding
Yuki Kimoto authored on 2016-04-05
20
has 'app';
copy gitweblite soruce code
root authored on 2012-11-23
21

            
cleanup branch_status
Yuki Kimoto authored on 2016-04-16
22
sub rep_work_current_branch {
23
  my ($self, $user, $project) = @_;
cleanup
Yuki Kimoto authored on 2013-05-14
24
  
cleanup branch_status
Yuki Kimoto authored on 2016-04-16
25
  my @cmd = $self->cmd_work_rep($user, $project, 'rev-parse',  '--abbrev-ref', 'HEAD');
26
  
27
  open my $fh, '-|', @cmd
28
    or croak "Can't get current branch: @cmd";
29
  my $current_branch = <$fh>;
30
  chomp $current_branch;
31
  
32
  return $current_branch;
cleanup
Yuki Kimoto authored on 2013-05-14
33
}
34

            
cleanup branch_status
Yuki Kimoto authored on 2016-04-16
35
sub branch {
cleanup
Yuki Kimoto authored on 2016-04-16
36
  my ($self, $rep_info, $branch_name) = @_;
cleanup branch
Yuki Kimoto authored on 2016-04-16
37
  
38
  # Branch
39
  $branch_name =~ s/^\*//;
40
  $branch_name =~ s/^\s*//;
41
  $branch_name =~ s/\s*$//;
42
  my $branch = {};
43
  $branch->{name} = $branch_name;
cleanup methods
Yuki Kimoto authored on 2016-04-16
44
  my $commit = $self->get_commit($rep_info, $branch_name);
cleanup branch
Yuki Kimoto authored on 2016-04-16
45
  $branch->{commit} = $commit;
46

            
47
  return $branch;
48
}
49

            
cleanup
Yuki Kimoto authored on 2013-05-14
50
sub branch_status {
cleanup
Yuki Kimoto authored on 2016-04-16
51
  my ($self, $rep_info, $branch1, $branch2) = @_;
cleanup
Yuki Kimoto authored on 2013-05-14
52
  
53
  # Branch status
54
  my $status = {ahead => 0, behind => 0};
cleanup cmd
Yuki Kimoto authored on 2016-04-16
55
  my @cmd = $self->cmd(
cleanup
Yuki Kimoto authored on 2016-04-16
56
    $rep_info,
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
57
    'rev-list',
58
    '--left-right',
59
    "$branch1...$branch2"
cleanup
Yuki Kimoto authored on 2013-05-14
60
  );
61
  open my $fh, '-|', @cmd
62
    or croak "Can't get branch status: @cmd";
63
  while (my $line = <$fh>) {
64
    if ($line =~ /^</) { $status->{behind}++ }
65
    elsif ($line =~ /^>/) { $status->{ahead}++ }
66
  }
67
  
68
  return $status;
69
}
70

            
add rename project and suppr...
Yuki Kimoto authored on 2013-05-24
71
sub no_merged_branch_h {
cleanup
Yuki Kimoto authored on 2016-04-16
72
  my ($self, $rep_info) = @_;
cleanup
Yuki Kimoto authored on 2013-05-14
73
  
74
  # No merged branches
75
  my $no_merged_branches_h = {};
76
  {
cleanup
Yuki Kimoto authored on 2016-04-16
77
    my @cmd = $self->cmd($rep_info, 'branch', '--no-merged');
add rename project and suppr...
Yuki Kimoto authored on 2013-05-24
78
    open my $fh, '-|', @cmd or return;
cleanup encoding
Yuki Kimoto authored on 2016-04-05
79
    my @lines = <$fh>;
80
    for my $branch_name (@lines) {
81
      $branch_name = $self->_dec($branch_name);
cleanup
Yuki Kimoto authored on 2013-05-14
82
      $branch_name =~ s/^\*//;
83
      $branch_name =~ s/^\s*//;
84
      $branch_name =~ s/\s*$//;
85
      $no_merged_branches_h->{$branch_name} = 1;
86
    }
87
  }
88
  
add rename project and suppr...
Yuki Kimoto authored on 2013-05-24
89
  return $no_merged_branches_h;
90
}
91

            
92
sub branches {
cleanup
Yuki Kimoto authored on 2016-04-16
93
  my ($self, $rep_info) = @_;
add rename project and suppr...
Yuki Kimoto authored on 2013-05-24
94
  
cleanup
Yuki Kimoto authored on 2013-05-14
95
  # Branches
cleanup
Yuki Kimoto authored on 2016-04-16
96
  my @cmd = $self->cmd($rep_info, 'branch');
cleanup
Yuki Kimoto authored on 2013-05-14
97
  open my $fh, '-|', @cmd or return;
98
  my $branches = [];
add rename project and suppr...
Yuki Kimoto authored on 2013-05-24
99
  my $start;
100
  my $no_merged_branches_h;
cleanup encoding
Yuki Kimoto authored on 2016-04-05
101
  my @lines = <$fh>;
102
  for my $branch_name (@lines) {
103
    $branch_name = $self->_dec($branch_name);
fix no merged branch not sho...
Yuki Kimoto authored on 2013-05-27
104
    $branch_name =~ s/^\*//;
105
    $branch_name =~ s/^\s*//;
106
    $branch_name =~ s/\s*$//;
cleanup
Yuki Kimoto authored on 2013-05-14
107
    
add rename project and suppr...
Yuki Kimoto authored on 2013-05-24
108
    # No merged branch
cleanup
Yuki Kimoto authored on 2016-04-16
109
    $no_merged_branches_h = $self->no_merged_branch_h($rep_info)
add rename project and suppr...
Yuki Kimoto authored on 2013-05-24
110
      unless $start++;
111
    
cleanup
Yuki Kimoto authored on 2013-05-14
112
    # Branch
cleanup
Yuki Kimoto authored on 2016-04-16
113
    my $branch = $self->branch($rep_info, $branch_name);
cleanup
Yuki Kimoto authored on 2013-05-14
114
    $branch->{no_merged} = 1 if $no_merged_branches_h->{$branch_name};
115
    push @$branches, $branch;
116
  }
117
  @$branches = sort { $a->{commit}{age} <=> $b->{commit}{age} } @$branches;
118
  
119
  return $branches;
120
}
121

            
122
sub branches_count {
cleanup
Yuki Kimoto authored on 2016-04-16
123
  my ($self, $rep_info) = @_;
cleanup
Yuki Kimoto authored on 2013-05-14
124
  
125
  # Branches count
cleanup
Yuki Kimoto authored on 2016-04-16
126
  my @cmd = $self->cmd($rep_info, 'branch');
cleanup
Yuki Kimoto authored on 2013-05-14
127
  open my $fh, '-|', @cmd or return;
128
  my @branches = <$fh>;
129
  my $branches_count = @branches;
130
  
131
  return $branches_count;
132
}
133

            
cleanup cmd
Yuki Kimoto authored on 2016-04-16
134
sub cmd {
cleanup
Yuki Kimoto authored on 2016-04-16
135
  my ($self, $rep_info, @command) = @_;
cleanup cmd
Yuki Kimoto authored on 2016-04-16
136
  
cleanup
Yuki Kimoto authored on 2016-04-16
137
  my $git_dir = $rep_info->{git_dir};
138
  my $work_tree = $rep_info->{work_tree};
cleanup cmd
Yuki Kimoto authored on 2016-04-16
139
  
140
  my @command_all = ($self->bin);
141
  if (defined $git_dir) {
142
    push @command_all, "--git-dir=$git_dir";
143
  }
144
  if (defined $work_tree) {
145
    push @command_all, "--work-tree=$work_tree";
146
  }
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
147
  push @command_all, @command;
cleanup cmd
Yuki Kimoto authored on 2016-04-16
148
  
149
  return @command_all;
150
}
151

            
added contributer count
Yuki Kimoto authored on 2013-01-28
152
sub authors {
cleanup
Yuki Kimoto authored on 2016-04-16
153
  my ($self, $rep_info, $rev, $file) = @_;
added contributer count
Yuki Kimoto authored on 2013-01-28
154
  
cleanup
Yuki Kimoto authored on 2013-05-14
155
  # Authors
cleanup authors
Yuki Kimoto authored on 2016-04-16
156
  my @cmd = $self->cmd(
cleanup
Yuki Kimoto authored on 2016-04-16
157
    $rep_info,
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
158
    'log',
159
    '--format=%an',
160
    $rev,
161
    '--',
162
    $file
cleanup blob page
Yuki Kimoto authored on 2013-03-19
163
  );
added contributer count
Yuki Kimoto authored on 2013-01-28
164
  open my $fh, "-|", @cmd
165
    or croak 500, "Open git-cat-file failed";
166
  my $authors = {};
cleanup encoding
Yuki Kimoto authored on 2016-04-05
167
  my @lines = <$fh>;
168
  for my $line (@lines) {
169
    $line = $self->_dec($line);
added contributer count
Yuki Kimoto authored on 2013-01-28
170
    $line =~ s/[\r\n]//g;
171
    $authors->{$line} = 1;
172
  }
173
  
174
  return [sort keys %$authors];
175
}
176

            
add blame method
Yuki Kimoto authored on 2013-08-10
177
sub blame {
cleanup
Yuki Kimoto authored on 2016-04-16
178
  my ($self, $rep_info, $rev, $file) = @_;
add blame method
Yuki Kimoto authored on 2013-08-10
179
  
180
  # Git blame
cleanup blame
Yuki Kimoto authored on 2016-04-16
181
  my @cmd = $self->cmd(
cleanup
Yuki Kimoto authored on 2016-04-16
182
    $rep_info,
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
183
    'blame',
184
    '--line-porcelain',
185
    $rev,
186
    '--',
187
    $file
add blame method
Yuki Kimoto authored on 2013-08-10
188
  );
189
  open my $fh, '-|', @cmd
190
    or croak "Can't git blame --line-porcelain";
191
  
192
  # Format lines
193
  my $blame_lines = [];
194
  my $blame_line;
add hot color to blame page
Yuki Kimoto authored on 2013-08-10
195
  my $max_author_time;
196
  my $min_author_time;
cleanup encoding
Yuki Kimoto authored on 2016-04-05
197
  my @lines = <$fh>;
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
198
  
cleanup methods
Yuki Kimoto authored on 2016-04-16
199
  my $enc = $self->decide_encoding($rep_info, \@lines);
cleanup encoding
Yuki Kimoto authored on 2016-04-05
200
  for my $line (@lines) {
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
201
    $line = decode($enc, $line);
add blame method
Yuki Kimoto authored on 2013-08-10
202
    chomp $line;
203
    
204
    if ($blame_line) {
205
      if ($line =~ /^author +(.+)/) {
206
        $blame_line->{author} = $1;
207
      }
208
      elsif ($line =~ /^author-mail +(.+)/) {
209
        $blame_line->{author_mail} = $1;
210
      }
improve blame design
Yuki Kimoto authored on 2013-08-10
211
      elsif ($line =~ /^author-time +(.+)/) {
212
        my $author_time = $1;
add hot color to blame page
Yuki Kimoto authored on 2013-08-10
213
        $blame_line->{author_time} = $author_time;
214
        $max_author_time = $author_time if !$max_author_time || $author_time > $max_author_time;
215
        $min_author_time = $author_time if !$min_author_time || $author_time < $min_author_time;
improve blame design
Yuki Kimoto authored on 2013-08-10
216
        my $author_age_string_date = $self->_age_string_date($author_time);
217
        $blame_line->{author_age_string_date} = $author_age_string_date;
improve blame page design
Yuki Kimoto authored on 2016-01-13
218
        my $author_age_string_date_local = $self->_age_string_date_local($author_time);
219
        $blame_line->{author_age_string_date_local} = $author_age_string_date_local;
improve blame design
Yuki Kimoto authored on 2013-08-10
220
      }
add blame method
Yuki Kimoto authored on 2013-08-10
221
      elsif ($line =~ /^summary +(.+)/) {
222
        $blame_line->{summary} = $1;
223
      }
224
      elsif ($line =~ /^\t(.+)?/) {
225
        my $content = $1;
226
        $content = '' unless defined $content;
227
        $blame_line->{content} = $content;
228
        push @$blame_lines, $blame_line;
229
        $blame_line = undef;
230
      }
231
    }
232
    elsif ($line =~ /^([a-fA-F0-9]{40}) +\d+ +(\d+)/) {
233
      $blame_line = {};
234
      $blame_line->{commit} = $1;
improve blame design
Yuki Kimoto authored on 2013-08-10
235
      $blame_line->{number} = $2;
add blame method
Yuki Kimoto authored on 2013-08-10
236
      if ($blame_lines->[-1]
237
        && $blame_lines->[-1]{commit} eq $blame_line->{commit})
238
      {
239
        $blame_line->{before_same_commit} = 1;
240
      }
241
    }
242
  }
243
  
add hot color to blame page
Yuki Kimoto authored on 2013-08-10
244
  my $blame = {
245
    lines => $blame_lines,
246
    max_author_time => $max_author_time,
247
    min_author_time => $min_author_time
248
  };
249
  
250
  return $blame;
add blame method
Yuki Kimoto authored on 2013-08-10
251
}
252

            
253
sub blob {
cleanup
Yuki Kimoto authored on 2016-04-16
254
  my ($self, $rep_info, $rev, $file) = @_;
add blame method
Yuki Kimoto authored on 2013-08-10
255
  
256
  # Blob
cleanup method
Yuki Kimoto authored on 2016-04-16
257
  my $hash = $self->path_to_hash($rep_info, $rev, $file, 'blob')
add blame method
Yuki Kimoto authored on 2013-08-10
258
    or croak 'Cannot find file';
cleanup blob
Yuki Kimoto authored on 2016-04-16
259
  my @cmd = $self->cmd(
cleanup
Yuki Kimoto authored on 2016-04-16
260
    $rep_info,
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
261
    'cat-file',
262
    'blob',
263
    $hash
add blame method
Yuki Kimoto authored on 2013-08-10
264
  );
265
  open my $fh, '-|', @cmd
266
    or croak "Can't cat $file, $hash";
267
  
268
  # Format lines
cleanup encoding
Yuki Kimoto authored on 2016-04-05
269
  my @lines = <$fh>;
270
  my @new_lines;
cleanup methods
Yuki Kimoto authored on 2016-04-16
271
  my $enc = $self->decide_encoding($rep_info, \@lines);
cleanup encoding
Yuki Kimoto authored on 2016-04-05
272
  for my $line (@lines) {
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
273
    $line = decode($enc, $line);
add blame method
Yuki Kimoto authored on 2013-08-10
274
    chomp $line;
cleanup encoding
Yuki Kimoto authored on 2016-04-05
275
    push @new_lines, $line;
add blame method
Yuki Kimoto authored on 2013-08-10
276
  }
277
  
cleanup encoding
Yuki Kimoto authored on 2016-04-05
278
  return \@new_lines;
add blame method
Yuki Kimoto authored on 2013-08-10
279
}
280

            
cleanup
Yuki Kimoto authored on 2013-05-14
281
sub blob_diffs {
cleanup
Yuki Kimoto authored on 2016-04-16
282
  my ($self, $rep_info, $rev1, $rev2, $diff_trees, $opt) = @_;
cleanup blob_diffs
Yuki Kimoto authored on 2016-04-16
283
  
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
284
  $opt //= {};
285
  my $ignore_space_change = $opt->{ignore_space_change};
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
286
  
cleanup
Yuki Kimoto authored on 2013-05-14
287
  return unless defined $rev1 && defined $rev2;
added commit page test
Yuki Kimoto authored on 2013-04-27
288
  
cleanup
Yuki Kimoto authored on 2013-05-14
289
  # Diff tree
cleanup blob_diffs
Yuki Kimoto authored on 2016-04-16
290
  my @cmd = $self->cmd(
cleanup
Yuki Kimoto authored on 2016-04-16
291
    $rep_info,
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
292
    'diff-tree',
293
    '-r',
294
    '-M',
295
    '--no-commit-id',
296
    '--patch-with-raw',
297
    ($ignore_space_change ? '--ignore-space-change' : ()),
298
    $rev1,
299
    $rev2,
300
    '--'
cleanup
Yuki Kimoto authored on 2013-03-19
301
  );
add --ignore-space-change fe...
Yuki Kimoto authored on 2014-12-09
302
  
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
303
  open my $fh, '-|', @cmd
304
    or croak('Open self-diff-tree failed');
cleanup
Yuki Kimoto authored on 2013-05-14
305
  my @diff_tree;
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
306
  my @diff_tree_lines = <$fh>;
cleanup methods
Yuki Kimoto authored on 2016-04-16
307
  my $diff_tree_enc = $self->decide_encoding($rep_info, \@diff_tree_lines);
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
308
  for my $line (@diff_tree_lines) {
309
    $line = decode($diff_tree_enc, $line);
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
310
    chomp $line;
cleanup
Yuki Kimoto authored on 2013-05-14
311
    push @diff_tree, $line if $line =~ /^:/;
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
312
    last if $line =~ /^\n/;
313
  }
314
  close $fh;
cleanup
Yuki Kimoto authored on 2013-05-14
315
  
316
  # Blob diffs
cleanup
Yuki Kimoto authored on 2013-05-14
317
  my $blob_diffs = [];
cleanup
Yuki Kimoto authored on 2013-05-14
318
  for my $line (@diff_tree) {
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
319
  
cleanup
Yuki Kimoto authored on 2013-05-14
320
    # File information
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
321
    chomp $line;
cleanup
Yuki Kimoto authored on 2013-05-14
322
    my $diffinfo = $self->parse_diff_tree_line($line);
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
323
    my $from_file = $diffinfo->{from_file};
324
    my $file = $diffinfo->{to_file};
325
    
cleanup
Yuki Kimoto authored on 2013-05-14
326
    # Blob diff
cleanup blob_diffs
Yuki Kimoto authored on 2016-04-16
327
    my @cmd = $self->cmd(
cleanup
Yuki Kimoto authored on 2016-04-16
328
      $rep_info,
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
329
      'diff-tree',
330
      '-r',
331
      '-M',
332
      '-p',
333
      ($ignore_space_change ? '--ignore-space-change' : ()),
334
      $rev1,
335
      $rev2,
336
      '--',
337
      (defined $from_file ? $from_file : ()),
338
      $file
cleanup
Yuki Kimoto authored on 2013-03-19
339
    );
cleanup
Yuki Kimoto authored on 2013-05-14
340
    open my $fh, '-|', @cmd
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
341
      or croak('Open self-diff-tree failed');
cleanup encoding
Yuki Kimoto authored on 2016-04-05
342
    my @lines = <$fh>;
cleanup methods
Yuki Kimoto authored on 2016-04-16
343
    my $enc = $self->decide_encoding($rep_info, \@lines);
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
344
    @lines = map { decode($enc, $_) } @lines;
cleanup
Yuki Kimoto authored on 2013-05-14
345
    close $fh;
add diff status bar to commi...
Yuki Kimoto authored on 2013-05-30
346
    my ($lines, $diff_info) = $self->parse_blob_diff_lines(\@lines);
cleanup
Yuki Kimoto authored on 2013-05-14
347
    my $blob_diff = {
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
348
      file => $file,
349
      from_file => $from_file,
add diff status bar to commi...
Yuki Kimoto authored on 2013-05-30
350
      lines => $lines,
351
      add_line_count => $diff_info->{add_line_count},
fixed blob diff line number ...
Yuki Kimoto authored on 2013-06-01
352
      delete_line_count => $diff_info->{delete_line_count},
353
      binary => $diff_info->{binary}
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
354
    };
355
    
add diff status bar to commi...
Yuki Kimoto authored on 2013-05-30
356
    # Diff tree info
cleanup
Yuki Kimoto authored on 2013-05-14
357
    for my $diff_tree (@$diff_trees) {
358
      if ($diff_tree->{to_file} eq $file) {
359
        $blob_diff->{status} = $diff_tree->{status};
add diff status bar to commi...
Yuki Kimoto authored on 2013-05-30
360
        $diff_tree->{add_line_count} = $diff_info->{add_line_count};
361
        $diff_tree->{delete_line_count} = $diff_info->{delete_line_count};
362
        $diff_tree->{add_block_count} = $diff_info->{add_block_count};
363
        $diff_tree->{delete_block_count} = $diff_info->{delete_block_count};
fixed blob diff line number ...
Yuki Kimoto authored on 2013-06-01
364
        $diff_tree->{binary} = $diff_info->{binary};
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
365
        last;
366
      }
367
    }
add diff status bar to commi...
Yuki Kimoto authored on 2013-05-30
368
    
cleanup
Yuki Kimoto authored on 2013-05-14
369
    push @$blob_diffs, $blob_diff;
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
370
  }
371
  
cleanup
Yuki Kimoto authored on 2013-05-14
372
  return $blob_diffs;
added compare page file chan...
Yuki Kimoto authored on 2013-02-07
373
}
374

            
binary data not shown
Yuki Kimoto authored on 2013-06-02
375
sub blob_is_image {
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
376
  my $self = shift;
binary data not shown
Yuki Kimoto authored on 2013-06-02
377
  
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
378
  my $mime_type = $self->blob_mime_type(@_);
binary data not shown
Yuki Kimoto authored on 2013-06-02
379
  
380
  return ($mime_type || '') =~ m#^image/#;
381
}
382

            
cleanup
Yuki Kimoto authored on 2013-05-14
383
sub blob_mime_type {
cleanup
Yuki Kimoto authored on 2016-04-16
384
  my ($self, $rep_info, $rev, $file) = @_;
cleanup blob and raw page
Yuki Kimoto authored on 2013-05-02
385
  
cleanup
Yuki Kimoto authored on 2013-05-14
386
  # Blob
cleanup method
Yuki Kimoto authored on 2016-04-16
387
  my $hash = $self->path_to_hash($rep_info, $rev, $file, 'blob')
cleanup blob and raw page
Yuki Kimoto authored on 2013-05-02
388
    or croak 'Cannot find file';
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
389
  my @cmd = $self->cmd(
cleanup
Yuki Kimoto authored on 2016-04-16
390
    $rep_info,
cleanup blob and raw page
Yuki Kimoto authored on 2013-05-02
391
    'cat-file',
392
    'blob',
cleanup
Yuki Kimoto authored on 2013-05-14
393
    $hash
cleanup blob and raw page
Yuki Kimoto authored on 2013-05-02
394
  );
395
  open my $fh, '-|', @cmd
cleanup
Yuki Kimoto authored on 2013-05-14
396
    or croak "Can't cat $file, $hash";
copy gitweblite soruce code
root authored on 2012-11-23
397

            
398
  return 'text/plain' unless $fh;
399
  
400
  # MIME type
401
  my $text_exts = $self->text_exts;
402
  for my $text_ext (@$text_exts) {
403
    my $ext = quotemeta($text_ext);
404
    return 'text/plain' if $file =~ /\.$ext$/i;
405
  }
406
  if (-T $fh) { return 'text/plain' }
407
  elsif (! $file) { return 'application/octet-stream' }
408
  elsif ($file =~ m/\.png$/i) { return 'image/png' }
409
  elsif ($file =~ m/\.gif$/i) { return 'image/gif' }
410
  elsif ($file =~ m/\.jpe?g$/i) { return 'image/jpeg'}
411
  else { return 'application/octet-stream'}
412
  
413
  return;
414
}
415

            
cleanup
Yuki Kimoto authored on 2013-05-14
416
sub blob_content_type {
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
417
  my $self = shift;
copy gitweblite soruce code
root authored on 2012-11-23
418
  
419
  # Content type
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
420
  my $type = $self->blob_mime_type(@_);
copy gitweblite soruce code
root authored on 2012-11-23
421
  if ($type eq 'text/plain') {
Renamed encoding to default_...
Tetsuya Hayashi authored on 2014-03-15
422
    $type .= "; charset=" . $self->default_encoding;
copy gitweblite soruce code
root authored on 2012-11-23
423
  }
424

            
425
  return $type;
426
}
427

            
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
428
sub blob_mode {
cleanup
Yuki Kimoto authored on 2016-04-16
429
  my ($self, $rep_info, $rev, $file) = @_;
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
430
  
cleanup
Yuki Kimoto authored on 2013-05-14
431
  # Blob mode
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
432
  $file =~ s#/+$##;
cleanup blob_mode
Yuki Kimoto authored on 2016-04-16
433
  my @cmd = $self->cmd(
cleanup
Yuki Kimoto authored on 2016-04-16
434
    $rep_info,
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
435
    'ls-tree',
436
    $rev,
437
    '--',
438
    $file
439
  );
440
  open my $fh, '-|', @cmd
441
    or croak 'Open git-ls-tree failed';
cleanup encoding
Yuki Kimoto authored on 2016-04-05
442
  my $line = <$fh>;
443
  $line = $self->_dec($line);
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
444
  close $fh or return;
445
  my ($mode) = ($line || '') =~ m/^([0-9]+) /;
446
  
447
  return $mode;
448
}
449

            
450
sub blob_raw {
cleanup
Yuki Kimoto authored on 2016-04-16
451
  my ($self, $rep_info, $rev, $path) = @_;
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
452
  
cleanup
Yuki Kimoto authored on 2013-05-14
453
  # Blob raw
cleanup
Yuki Kimoto authored on 2016-04-16
454
  my @cmd = $self->cmd($rep_info, 'cat-file', 'blob', "$rev:$path");
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
455
  open my $fh, "-|", @cmd
456
    or croak 500, "Open git-cat-file failed";
457
  local $/;
cleanup blob_raw
Yuki Kimoto authored on 2016-04-16
458
  my $blob_raw = <$fh>;
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
459

            
460
  close $fh or croak 'Reading git-shortlog failed';
461
  
462
  return $blob_raw;
463
}
464

            
cleanup
Yuki Kimoto authored on 2013-05-14
465
sub blob_size {
cleanup
Yuki Kimoto authored on 2016-04-16
466
  my ($self, $rep_info, $rev, $file) = @_;
added file size to blob page
Yuki Kimoto authored on 2013-01-29
467
  
cleanup
Yuki Kimoto authored on 2013-05-14
468
  # Blob size(KB)
cleanup blob_size
Yuki Kimoto authored on 2016-04-16
469
  my @cmd = $self->cmd(
cleanup
Yuki Kimoto authored on 2016-04-16
470
    $rep_info,
cleanup blob page
Yuki Kimoto authored on 2013-03-19
471
    'cat-file',
472
    '-s',
473
    "$rev:$file"
474
  );
added file size to blob page
Yuki Kimoto authored on 2013-01-29
475
  open my $fh, "-|", @cmd
476
    or croak 500, "Open cat-file failed";
cleanup encoding
Yuki Kimoto authored on 2016-04-05
477
  my $size = <$fh>;
478
  $size = $self->_dec($size);
added file size to blob page
Yuki Kimoto authored on 2013-01-29
479
  chomp $size;
480
  close $fh or croak 'Reading cat-file failed';
481
  
cleanup
Yuki Kimoto authored on 2013-05-14
482
  # Format
483
  my $size_f = sprintf('%.3f', $size / 1000);
484
  $size_f =~ s/0+$//;
improved blob page desing
Yuki Kimoto authored on 2013-05-02
485
  
cleanup
Yuki Kimoto authored on 2013-05-14
486
  return $size_f;
added file size to blob page
Yuki Kimoto authored on 2013-01-29
487
}
488

            
improved create repository f...
Yuki Kimoto authored on 2013-03-21
489
sub check_head_link {
490
  my ($self, $dir) = @_;
added separeted commit getti...
Yuki Kimoto authored on 2013-02-04
491
  
improved create repository f...
Yuki Kimoto authored on 2013-03-21
492
  # Chack head
493
  my $head_file = "$dir/HEAD";
494
  return ((-e $head_file) ||
495
    (-l $head_file && readlink($head_file) =~ /^refs\/heads\//));
496
}
added separeted commit getti...
Yuki Kimoto authored on 2013-02-04
497

            
added commits number
Yuki Kimoto authored on 2012-11-28
498
sub commits_number {
cleanup
Yuki Kimoto authored on 2016-04-16
499
  my ($self, $rep_info, $ref) = @_;
added commits number
Yuki Kimoto authored on 2012-11-28
500
  
501
  # Command "git diff-tree"
cleanup
Yuki Kimoto authored on 2016-04-16
502
  my @cmd = $self->cmd($rep_info, 'shortlog', '-s', $ref);
added commits number
Yuki Kimoto authored on 2012-11-28
503
  open my $fh, "-|", @cmd
504
    or croak 500, "Open git-shortlog failed";
cleanup encoding
Yuki Kimoto authored on 2016-04-05
505
  my @commits_infos = <$fh>;
506
  @commits_infos = map { chomp; $self->_dec($_) } @commits_infos;
added commits number
Yuki Kimoto authored on 2012-11-28
507
  close $fh or croak 'Reading git-shortlog failed';
508
  
509
  my $commits_num = 0;
510
  for my $commits_info (@commits_infos) {
511
    if ($commits_info =~ /^ *([0-9]+)/) {
512
      $commits_num += $1;
513
    }
514
  }
515
  
516
  return $commits_num;
517
}
518

            
cleanup
Yuki Kimoto authored on 2013-05-14
519
sub exists_branch {
cleanup descriptioN
Yuki Kimoto authored on 2016-04-16
520
  my ($self, $rep) = @_;
cleanup
Yuki Kimoto authored on 2013-05-14
521
  
522
  # Exists branch
cleanup descriptioN
Yuki Kimoto authored on 2016-04-16
523
  my @cmd = $self->cmd($rep, 'branch');
cleanup
Yuki Kimoto authored on 2013-05-14
524
  open my $fh, "-|", @cmd
525
    or croak 'git branch failed';
526
  local $/;
cleanup descriptioN
Yuki Kimoto authored on 2016-04-16
527
  my $branch = <$fh>;
cleanup
Yuki Kimoto authored on 2013-05-14
528
  
cleanup descriptioN
Yuki Kimoto authored on 2016-04-16
529
  return $branch ne '' ? 1 : 0;
cleanup
Yuki Kimoto authored on 2013-05-14
530
}
531

            
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
532
sub delete_branch {
cleanup descriptioN
Yuki Kimoto authored on 2016-04-16
533
  my ($self, $rep, $branch) = @_;
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
534
  
cleanup descriptioN
Yuki Kimoto authored on 2016-04-16
535
  my $branches = $self->branches($rep);
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
536
  my $exists;
537
  for my $b (@$branches) {
538
    if ($branch eq $b->{name}) {
539
      $exists = 1;
540
      next;
541
    }
542
  }
543
  
544
  if ($exists) {
cleanup descriptioN
Yuki Kimoto authored on 2016-04-16
545
    my @cmd = $self->cmd($rep, 'branch', '-D', $branch);
fix bug that in CGI reposito...
Yuki Kimoto authored on 2015-11-05
546
    Gitprep::Util::run_command(@cmd)
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
547
      or croak "Branch deleting failed. Can't delete branch $branch";
548
  }
549
  else {
550
    croak "Branch deleteting failed.. branchg $branch is not exists";
551
  }
552
}
553

            
added project rename feature
Yuki Kimoto authored on 2013-03-25
554
sub description {
cleanup descriptioN
Yuki Kimoto authored on 2016-04-16
555
  my ($self, $rep, $description) = @_;
added project rename feature
Yuki Kimoto authored on 2013-03-25
556
  
cleanup descriptioN
Yuki Kimoto authored on 2016-04-16
557
  my $git_dir = $rep->{git_dir};
558
  my $file = "$git_dir/description";
added project rename feature
Yuki Kimoto authored on 2013-03-25
559
  
560
  if (defined $description) {
561
    # Write description
562
    open my $fh, '>',$file
563
      or croak "Can't open file $rep: $!";
564
    print $fh encode('UTF-8', $description)
565
      or croak "Can't write description: $!";
566
    close $fh;
567
  }
568
  else {
569
    # Read description
added not exists repository ...
Yuki Kimoto authored on 2013-05-15
570
    return unless -f $file;
cleanup encoding
Yuki Kimoto authored on 2016-04-05
571
    my $description = $self->_slurp($file) || '';
572
    $description = $self->_dec($description);
added project rename feature
Yuki Kimoto authored on 2013-03-25
573
    return $description;
574
  }
575
}
576

            
cleanup
Yuki Kimoto authored on 2013-05-14
577
sub diff_tree {
cleanup method
Yuki Kimoto authored on 2016-04-16
578
  my ($self, $rep_info, $rev, $parent, $opt) = @_;
add --ignore-space-change fe...
Yuki Kimoto authored on 2014-12-09
579
  
580
  $opt ||= {};
581
  my $ignore_space_change = $opt->{ignore_space_change};
add diff status bar to commi...
Yuki Kimoto authored on 2013-05-30
582
  
copy gitweblite soruce code
root authored on 2012-11-23
583
  # Root
584
  $parent = '--root' unless defined $parent;
585

            
cleanup
Yuki Kimoto authored on 2013-03-19
586
  # Get diff tree
cleanup method
Yuki Kimoto authored on 2016-04-16
587
  my @cmd = $self->cmd(
588
    $rep_info,
cleanup
Yuki Kimoto authored on 2013-03-19
589
    "diff-tree",
590
    '-r',
591
    '--no-commit-id',
592
    '-M',
add --ignore-space-change fe...
Yuki Kimoto authored on 2014-12-09
593
    ($ignore_space_change ? '--ignore-space-change' : ()),
impved merge commit logic
Yuki Kimoto authored on 2013-06-01
594
    $parent,
595
    $rev,
cleanup
Yuki Kimoto authored on 2013-03-19
596
    '--'
597
  );
add --ignore-space-change fe...
Yuki Kimoto authored on 2014-12-09
598
  
copy gitweblite soruce code
root authored on 2012-11-23
599
  open my $fh, "-|", @cmd
600
    or croak 500, "Open git-diff-tree failed";
cleanup encoding
Yuki Kimoto authored on 2016-04-05
601
  my @diff_tree = <$fh>;
602
  @diff_tree = map { chomp; $self->_dec($_) } @diff_tree;
copy gitweblite soruce code
root authored on 2012-11-23
603
  close $fh or croak 'Reading git-diff-tree failed';
604
  
605
  # Parse "git diff-tree" output
606
  my $diffs = [];
cleanup
Yuki Kimoto authored on 2013-05-14
607
  for my $line (@diff_tree) {
608
    my $diff = $self->parsed_diff_tree_line($line);
copy gitweblite soruce code
root authored on 2012-11-23
609
    
impved merge commit logic
Yuki Kimoto authored on 2013-06-01
610
    my ($to_mode_oct, $to_mode_str, $to_file_type);
611
    my ($from_mode_oct, $from_mode_str, $from_file_type);
612
    if ($diff->{to_mode} ne ('0' x 6)) {
613
      $to_mode_oct = oct $diff->{to_mode};
614
      if (S_ISREG($to_mode_oct)) { # only for regular file
615
        $to_mode_str = sprintf('%04o', $to_mode_oct & 0777); # permission bits
copy gitweblite soruce code
root authored on 2012-11-23
616
      }
impved merge commit logic
Yuki Kimoto authored on 2013-06-01
617
      $to_file_type = $self->file_type($diff->{to_mode});
618
    }
619
    if ($diff->{from_mode} ne ('0' x 6)) {
620
      $from_mode_oct = oct $diff->{from_mode};
621
      if (S_ISREG($from_mode_oct)) { # only for regular file
622
        $from_mode_str = sprintf('%04o', $from_mode_oct & 0777); # permission bits
copy gitweblite soruce code
root authored on 2012-11-23
623
      }
impved merge commit logic
Yuki Kimoto authored on 2013-06-01
624
      $from_file_type = $self->file_type($diff->{from_mode});
copy gitweblite soruce code
root authored on 2012-11-23
625
    }
impved merge commit logic
Yuki Kimoto authored on 2013-06-01
626
    
627
    $diff->{to_mode_str} = $to_mode_str;
628
    $diff->{to_mode_oct} = $to_mode_oct;
629
    $diff->{to_file_type} = $to_file_type;
630
    $diff->{from_mode_str} = $from_mode_str;
631
    $diff->{from_mode_oct} = $from_mode_oct;
632
    $diff->{from_file_type} = $from_file_type;
633

            
634
    push @$diffs, $diff;
copy gitweblite soruce code
root authored on 2012-11-23
635
  }
636
  
637
  return $diffs;
638
}
639

            
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
640
sub file_type {
641
  my ($self, $mode) = @_;
642
  
643
  # File type
644
  if ($mode !~ m/^[0-7]+$/) { return $mode }
645
  else { $mode = oct $mode }
646
  if ($self->_s_isgitlink($mode)) { return 'submodule' }
647
  elsif (S_ISDIR($mode & S_IFMT)) { return 'directory' }
648
  elsif (S_ISLNK($mode)) { return 'symlink' }
649
  elsif (S_ISREG($mode)) { return 'file' }
650
  else { return 'unknown' }
651
  
652
  return
653
}
654

            
655
sub file_type_long {
656
  my ($self, $mode) = @_;
657
  
cleanup
Yuki Kimoto authored on 2013-05-14
658
  # File type long
added branch deleting featur...
Yuki Kimoto authored on 2013-05-05
659
  if ($mode !~ m/^[0-7]+$/) { return $mode }
660
  else { $mode = oct $mode }
661
  if ($self->_s_isgitlink($mode)) { return 'submodule' }
662
  elsif (S_ISDIR($mode & S_IFMT)) { return 'directory' }
663
  elsif (S_ISLNK($mode)) { return 'symlink' }
664
  elsif (S_ISREG($mode)) {
665
    if ($mode & S_IXUSR) { return 'executable file' }
666
    else { return 'file' }
667
  }
668
  else { return 'unknown' }
669
  
670
  return;
671
}
672

            
cleanup
Yuki Kimoto authored on 2013-05-14
673
sub forward_commits {
cleanup method
Yuki Kimoto authored on 2016-04-16
674
  my ($self, $rep_info, $rev1, $rev2) = @_;
setting page
Yuki Kimoto authored on 2013-03-24
675
  
cleanup
Yuki Kimoto authored on 2013-05-14
676
  # Forwarding commits
cleanup method
Yuki Kimoto authored on 2016-04-16
677
  my @cmd = $self->cmd(
678
    $rep_info,
cleanup
Yuki Kimoto authored on 2013-05-14
679
    'rev-list',
680
    '--left-right',
681
    "$rev1...$rev2"
682
  );
683
  open my $fh, '-|', @cmd
684
    or croak "Can't get info: @cmd";
685
  my $commits = [];
686
  while (my $line = <$fh>) {
687
    if ($line =~ /^>(.+)\s/) {
688
      my $rev = $1;
cleanup methods
Yuki Kimoto authored on 2016-04-16
689
      my $commit = $self->get_commit($rep_info, $rev);
cleanup
Yuki Kimoto authored on 2013-05-14
690
      push @$commits, $commit;
added merged branches to bra...
Yuki Kimoto authored on 2013-05-03
691
    }
692
  }
693
  
cleanup
Yuki Kimoto authored on 2013-05-14
694
  return $commits;
added merged branches to bra...
Yuki Kimoto authored on 2013-05-03
695
}
696

            
cleanup
Yuki Kimoto authored on 2013-05-14
697
sub path_to_hash {
cleanup method
Yuki Kimoto authored on 2016-04-16
698
  my ($self, $rep_info, $rev, $path, $type) = @_;
copy gitweblite soruce code
root authored on 2012-11-23
699
  
700
  # Get blob id or tree id (command "git ls-tree")
701
  $path =~ s#/+$##;
cleanup method
Yuki Kimoto authored on 2016-04-16
702
  my @cmd = $self->cmd(
703
    $rep_info,
cleanup
Yuki Kimoto authored on 2013-03-19
704
    'ls-tree',
cleanup
Yuki Kimoto authored on 2013-04-29
705
    $rev,
cleanup
Yuki Kimoto authored on 2013-03-19
706
    '--',
707
    $path
708
  );
copy gitweblite soruce code
root authored on 2012-11-23
709
  open my $fh, '-|', @cmd
710
    or croak 'Open git-ls-tree failed';
cleanup encoding
Yuki Kimoto authored on 2016-04-05
711
  my $line = <$fh>;
712
  $line = $self->_dec($line);
copy gitweblite soruce code
root authored on 2012-11-23
713
  close $fh or return;
714
  my ($t, $id) = ($line || '') =~ m/^[0-9]+ (.+) ([0-9a-fA-F]{40})\t/;
change markdown engine to Te...
Yuki Kimoto authored on 2013-10-07
715
  $t ||= '';
copy gitweblite soruce code
root authored on 2012-11-23
716
  return if defined $type && $type ne $t;
717

            
718
  return $id;
719
}
720

            
cleanup
Yuki Kimoto authored on 2013-05-14
721

            
722
sub last_activity {
cleanup method
Yuki Kimoto authored on 2016-04-16
723
  my ($self, $rep) = @_;
added branch and tag refs to...
Yuki Kimoto authored on 2013-04-26
724
  
cleanup
Yuki Kimoto authored on 2013-05-14
725
  # Command "git for-each-ref"
cleanup method
Yuki Kimoto authored on 2016-04-16
726
  my @cmd = $self->cmd(
727
    $rep,
cleanup
Yuki Kimoto authored on 2013-05-14
728
    'for-each-ref',
729
    '--format=%(committer)',
730
    '--sort=-committerdate',
731
    '--count=1', 'refs/heads'
added branch and tag refs to...
Yuki Kimoto authored on 2013-04-26
732
  );
cleanup
Yuki Kimoto authored on 2013-05-14
733
  open my $fh, '-|', @cmd or return;
cleanup encoding
Yuki Kimoto authored on 2016-04-05
734
  my $most_recent = <$fh>;
735
  $most_recent = $self->_dec($most_recent);
cleanup
Yuki Kimoto authored on 2013-05-14
736
  close $fh or return;
added branch and tag refs to...
Yuki Kimoto authored on 2013-04-26
737
  
cleanup
Yuki Kimoto authored on 2013-05-14
738
  # Parse most recent
739
  if (defined $most_recent &&
740
      $most_recent =~ / (\d+) [-+][01]\d\d\d$/) {
741
    my $timestamp = $1;
742
    my $age = time - $timestamp;
743
    return ($age, $self->_age_string($age));
added branch and tag refs to...
Yuki Kimoto authored on 2013-04-26
744
  }
745
  
cleanup
Yuki Kimoto authored on 2013-05-14
746
  return;
747
}
748

            
749
sub parse_rev_path {
cleanup tags
Yuki Kimoto authored on 2016-04-16
750
  my ($self, $rep_info, $rev_path) = @_;
copy gitweblite soruce code
root authored on 2012-11-23
751
  
cleanup
Yuki Kimoto authored on 2013-05-14
752
  # References
cleanup parse_rev_path
Yuki Kimoto authored on 2016-04-16
753
  my @cmd = $self->cmd(
cleanup tags
Yuki Kimoto authored on 2016-04-16
754
    $rep_info,
cleanup
Yuki Kimoto authored on 2013-05-14
755
    'show-ref',
756
    '--dereference'
cleanup
Yuki Kimoto authored on 2013-03-19
757
  );
cleanup
Yuki Kimoto authored on 2013-05-14
758
  open my $fh, '-|', @cmd
759
    or return;
760
  my $refs = [];
cleanup encoding
Yuki Kimoto authored on 2016-04-05
761
  my @lines = <$fh>;
762
  for my $line (@lines) {
763
    $line = $self->_dec($line);
cleanup
Yuki Kimoto authored on 2013-05-14
764
    chomp $line;
765
    if ($line =~ m!^[0-9a-fA-F]{40}\s(refs/((?:heads|tags)/(.*)))$!) {
766
      push @$refs, $1, $2, $3;
767
    }
768
  }
copy gitweblite soruce code
root authored on 2012-11-23
769
  close $fh or return;
770
  
cleanup
Yuki Kimoto authored on 2013-05-14
771
  @$refs = sort {
772
    my @a_match = $a =~ /(\/)/g;
773
    my @b_match = $b =~ /(\/)/g;
774
    scalar @b_match <=> scalar @a_match;
775
  } @$refs;
776
  
777
  for my $ref (@$refs) {
778
    $rev_path =~ m#/$#;
779
    if ($rev_path =~ m#^(\Q$ref\E)/(.+)#) {
780
      my $rev = $1;
781
      my $path = $2;
782
      return ($rev, $path);
783
    }
784
    elsif ($rev_path eq $ref) {
785
      return ($rev_path, '');
786
    }
copy gitweblite soruce code
root authored on 2012-11-23
787
  }
788
  
cleanup
Yuki Kimoto authored on 2013-05-14
789
  if ($rev_path) {
790
    my ($rev, $path) = split /\//, $rev_path, 2;
791
    $path = '' unless defined $path;
792
    return ($rev, $path);
793
  }
794

            
copy gitweblite soruce code
root authored on 2012-11-23
795
  return;
796
}
797

            
798
sub object_type {
cleanup tags
Yuki Kimoto authored on 2016-04-16
799
  my ($self, $rep_info, $rev) = @_;
copy gitweblite soruce code
root authored on 2012-11-23
800
  
cleanup
Yuki Kimoto authored on 2013-03-19
801
  # Get object type
cleanup tags
Yuki Kimoto authored on 2016-04-16
802
  my @cmd = $self->cmd(
803
    $rep_info,
cleanup
Yuki Kimoto authored on 2013-03-19
804
    'cat-file',
805
    '-t',
impved merge commit logic
Yuki Kimoto authored on 2013-06-01
806
    $rev
cleanup
Yuki Kimoto authored on 2013-03-19
807
  );
copy gitweblite soruce code
root authored on 2012-11-23
808
  open my $fh, '-|', @cmd  or return;
cleanup encoding
Yuki Kimoto authored on 2016-04-05
809
  my $type = <$fh>;
810
  $type = $self->_dec($type);
copy gitweblite soruce code
root authored on 2012-11-23
811
  close $fh or return;
812
  chomp $type;
813
  
814
  return $type;
815
}
816

            
show deleted repository in u...
Yuki Kimoto authored on 2013-05-15
817
sub repository {
cleanup tags
Yuki Kimoto authored on 2016-04-16
818
  my ($self, $rep_info) = @_;
show deleted repository in u...
Yuki Kimoto authored on 2013-05-15
819

            
cleanup
Yuki Kimoto authored on 2016-04-16
820
  return unless -d $rep_info->{git_dir};
Fixed repositories page
Yuki Kimoto authored on 2012-11-23
821
  
show deleted repository in u...
Yuki Kimoto authored on 2013-05-15
822
  my $rep = {};
cleanup tags
Yuki Kimoto authored on 2016-04-16
823
  my @activity = $self->last_activity($rep_info);
show deleted repository in u...
Yuki Kimoto authored on 2013-05-15
824
  if (@activity) {
825
    $rep->{age} = $activity[0];
826
    $rep->{age_string} = $activity[1];
Fixed repositories page
Yuki Kimoto authored on 2012-11-23
827
  }
show deleted repository in u...
Yuki Kimoto authored on 2013-05-15
828
  else { $rep->{age} = 0 }
829
  
cleanup tags
Yuki Kimoto authored on 2016-04-16
830
  my $description = $self->description($rep_info) || '';
show deleted repository in u...
Yuki Kimoto authored on 2013-05-15
831
  $rep->{description} = $self->_chop_str($description, 25, 5);
cleanup
Yuki Kimoto authored on 2013-03-19
832
  
show deleted repository in u...
Yuki Kimoto authored on 2013-05-15
833
  return $rep;
Fixed repositories page
Yuki Kimoto authored on 2012-11-23
834
}
835

            
cleanup
Yuki Kimoto authored on 2013-05-14
836
sub references {
cleanup tags
Yuki Kimoto authored on 2016-04-16
837
  my ($self, $rep_info, $type) = @_;
cleanup
Yuki Kimoto authored on 2013-05-14
838
  
839
  $type ||= '';
840
  
841
  # Branches or tags
cleanup tags
Yuki Kimoto authored on 2016-04-16
842
  my @cmd = $self->cmd(
843
    $rep_info,
cleanup
Yuki Kimoto authored on 2013-05-14
844
    'show-ref',
845
    '--dereference',
846
    (
847
      $type eq 'heads' ? ('--heads') :
848
      $type eq 'tags' ? ('--tags') :
849
      ()
850
    )
851
  );
852
  
853
  open my $fh, '-|', @cmd
854
    or return;
855
  
856
  # Parse references
857
  my %refs;
858
  my $type_re = $type ? $type : '(?:heads|tags)';
cleanup encoding
Yuki Kimoto authored on 2016-04-05
859
  my @lines = <$fh>;
860
  for my $line (@lines) {
861
    $line = $self->_dec($line);
cleanup
Yuki Kimoto authored on 2013-05-14
862
    chomp $line;
863
    if ($line =~ m!^([0-9a-fA-F]{40})\srefs/$type_re/(.*)$!) {
improved tag and branch refe...
Yuki Kimoto authored on 2013-06-03
864
      my $rev = $1;
865
      my $ref = $2;
866
      $ref =~ s/\^\{\}//;
867
      if (defined $refs{$rev}) { push @{$refs{$rev}}, $ref }
868
      else { $refs{$rev} = [$ref] }
cleanup
Yuki Kimoto authored on 2013-05-14
869
    }
870
  }
871
  close $fh or return;
872
  
873
  return \%refs;
874
}
875

            
copy gitweblite soruce code
root authored on 2012-11-23
876
sub short_id {
877
  my ($self, $project) = (shift, shift);
878
  
879
  # Short id
880
  return $self->id($project, @_, '--short=7');
881
}
882

            
improved tag page design
Yuki Kimoto authored on 2013-05-01
883
sub tags_count {
cleanup methods
Yuki Kimoto authored on 2016-04-16
884
  my ($self, $rep_info) = @_;
improved tag page design
Yuki Kimoto authored on 2013-05-01
885
  
886
  my $limit = 1000;
887
  
888
  # Get tags
cleanup methods
Yuki Kimoto authored on 2016-04-16
889
  my @cmd = $self->cmd(
890
    $rep_info,
improved tag page design
Yuki Kimoto authored on 2013-05-01
891
    'for-each-ref',
892
    ($limit ? '--count='.($limit+1) : ()),
893
    'refs/tags'
894
  );
895
  open my $fh, '-|', @cmd or return;
896
  
897
  # Tags count
898
  my @lines = <$fh>;
899
  
900
  return scalar @lines;
901
}
902

            
copy gitweblite soruce code
root authored on 2012-11-23
903
sub tags {
cleanup tags
Yuki Kimoto authored on 2016-04-16
904
  my ($self, $rep_info, $limit, $count, $offset) = @_;
improved tag page design
Yuki Kimoto authored on 2013-05-01
905
  
906
  $limit ||= 1000;
907
  $count ||= 50;
908
  $offset ||= 0;
cleanup
Yuki Kimoto authored on 2013-03-19
909
  
910
  # Get tags
cleanup tags
Yuki Kimoto authored on 2016-04-16
911
  my @cmd = $self->cmd(
912
    $rep_info,
cleanup
Yuki Kimoto authored on 2013-03-19
913
    'for-each-ref',
914
    ($limit ? '--count='.($limit+1) : ()),
915
    '--sort=-creatordate',
916
    '--format=%(objectname) %(objecttype) %(refname) '
917
      . '%(*objectname) %(*objecttype) %(subject)%00%(creator)',
918
    'refs/tags'
919
  );
copy gitweblite soruce code
root authored on 2012-11-23
920
  open my $fh, '-|', @cmd or return;
921
  
improved tag page design
Yuki Kimoto authored on 2013-05-01
922
  
copy gitweblite soruce code
root authored on 2012-11-23
923
  # Parse Tags
924
  my @tags;
improved tag page design
Yuki Kimoto authored on 2013-05-01
925
  my $line_num = 1;
cleanup encoding
Yuki Kimoto authored on 2016-04-05
926
  my @lines = <$fh>;
927
  for my $line (@lines) {
928
    $line = $self->_dec($line);
copy gitweblite soruce code
root authored on 2012-11-23
929
    
improved tag page design
Yuki Kimoto authored on 2013-05-01
930
    if ($line_num > $offset && $line_num < $offset + $count + 1) {
931
    
932
      my %tag;
933

            
934
      chomp $line;
935
      my ($refinfo, $creatorinfo) = split(/\0/, $line);
936
      my ($id, $type, $name, $refid, $reftype, $title) = split(' ', $refinfo, 6);
937
      my ($creator, $epoch, $tz) =
938
        ($creatorinfo =~ /^(.*) ([0-9]+) (.*)$/);
939
      $tag{fullname} = $name;
940
      $name =~ s!^refs/tags/!!;
941

            
942
      $tag{type} = $type;
943
      $tag{id} = $id;
944
      $tag{name} = $name;
945
      if ($type eq 'tag') {
946
        $tag{subject} = $title;
947
        $tag{reftype} = $reftype;
948
        $tag{refid}   = $refid;
copy gitweblite soruce code
root authored on 2012-11-23
949
      } else {
improved tag page design
Yuki Kimoto authored on 2013-05-01
950
        $tag{reftype} = $type;
951
        $tag{refid}   = $id;
copy gitweblite soruce code
root authored on 2012-11-23
952
      }
953

            
improved tag page design
Yuki Kimoto authored on 2013-05-01
954
      if ($type eq 'tag' || $type eq 'commit') {
955
        $tag{epoch} = $epoch;
956
        if ($epoch) {
957
          $tag{age} = $self->_age_string(time - $tag{epoch});
958
        } else {
959
          $tag{age} = 'unknown';
960
        }
961
      }
962
      
963
      $tag{comment_short} = $self->_chop_str($tag{subject}, 30, 5)
964
        if $tag{subject};
965

            
cleanup methods
Yuki Kimoto authored on 2016-04-16
966
      $tag{commit} = $self->get_commit($rep_info, $name);
improved tag page design
Yuki Kimoto authored on 2013-05-01
967

            
968
      push @tags, \%tag;
969
    }
970
    $line_num++;
copy gitweblite soruce code
root authored on 2012-11-23
971
  }
improved tag page design
Yuki Kimoto authored on 2013-05-01
972
  
copy gitweblite soruce code
root authored on 2012-11-23
973
  close $fh;
974

            
975
  return \@tags;
976
}
977

            
improved project page design
Yuki Kimoto authored on 2013-04-29
978
sub last_change_commit {
cleanup methods
Yuki Kimoto authored on 2016-04-16
979
  my ($self, $rep_info, $rev, $file) = @_;
improved project page design
Yuki Kimoto authored on 2013-04-29
980
  
981
  my $commit_log = {};
982
  $file = '' unless defined $file;
983
  
cleanup methods
Yuki Kimoto authored on 2016-04-16
984
  my @cmd = $self->cmd(
985
    $rep_info,
improved project page design
Yuki Kimoto authored on 2013-04-29
986
    '--no-pager',
987
    'log',
988
    '-n',
989
    '1',
990
    '--pretty=format:%H', 
991
    $rev,
992
    '--',
993
    $file
994
  );
995
  open my $fh, '-|', @cmd
996
    or croak 'Open git-log failed';
997
  
998
  local $/;
cleanup encoding
Yuki Kimoto authored on 2016-04-05
999
  my $commit_log_text = <$fh>;
1000
  $commit_log_text = $self->_dec($commit_log_text);
improved project page design
Yuki Kimoto authored on 2013-04-29
1001
  
1002
  my $commit;
1003
  if ($commit_log_text =~ /^([0-9a-zA-Z]+)/) {
1004
    my $rev = $1;
cleanup methods
Yuki Kimoto authored on 2016-04-16
1005
    $commit = $self->get_commit($rep_info, $rev);
improved project page design
Yuki Kimoto authored on 2013-04-29
1006
  }
1007
  
1008
  return $commit;
1009
}
1010

            
cleanup
Yuki Kimoto authored on 2013-05-14
1011
sub parse_blob_diff_lines {
cleanup commit page
Yuki Kimoto authored on 2013-04-12
1012
  my ($self, $lines) = @_;
fixed blob diff line number ...
Yuki Kimoto authored on 2013-06-01
1013

            
1014
  my $diff_info = {};
1015

            
added commit page
Yuki Kimoto authored on 2013-01-29
1016
  # Parse
1017
  my @lines;
added line number logic to c...
Yuki Kimoto authored on 2013-04-12
1018
  my $next_before_line_num;
1019
  my $next_after_line_num;
add diff status bar to commi...
Yuki Kimoto authored on 2013-05-30
1020
  my $add_line_count = 0;
1021
  my $delete_line_count = 0;
cleanup commit page
Yuki Kimoto authored on 2013-04-12
1022
  for my $line (@$lines) {
fixed blob diff line number ...
Yuki Kimoto authored on 2013-06-01
1023
    
added commit page
Yuki Kimoto authored on 2013-01-29
1024
    chomp $line;
1025
    
improved commit page design
Yuki Kimoto authored on 2013-04-12
1026
    my $class;
cleanup commit page
Yuki Kimoto authored on 2013-04-12
1027
    my $before_line_num;
1028
    my $after_line_num;
improved commit page design
Yuki Kimoto authored on 2013-04-12
1029
    
fixed blob diff line number ...
Yuki Kimoto authored on 2013-06-01
1030
    if ($line =~ /^@@\s-(\d+)(?:,\d+)?\s\+(\d+)/) {
added line number logic to c...
Yuki Kimoto authored on 2013-04-12
1031
      $next_before_line_num = $1;
1032
      $next_after_line_num = $2;
1033
      
1034
      $before_line_num = '...';
1035
      $after_line_num = '...';
1036
      
1037
      $class = 'chunk_header';
1038
    }
added line number to commit ...
Yuki Kimoto authored on 2013-04-12
1039
    elsif ($line =~ /^\+\+\+/ || $line =~ /^---/) { next }
1040
    elsif ($line =~ /^\-/) {
added line number logic to c...
Yuki Kimoto authored on 2013-04-12
1041
      $class = 'from_file';
added line number to commit ...
Yuki Kimoto authored on 2013-04-12
1042
      $before_line_num = $next_before_line_num++;
added line number logic to c...
Yuki Kimoto authored on 2013-04-12
1043
      $after_line_num = '';
add diff status bar to commi...
Yuki Kimoto authored on 2013-05-30
1044
      $delete_line_count++;
added line number logic to c...
Yuki Kimoto authored on 2013-04-12
1045
    }
added line number to commit ...
Yuki Kimoto authored on 2013-04-12
1046
    elsif ($line =~ /^\+/) {
added line number logic to c...
Yuki Kimoto authored on 2013-04-12
1047
      $class = 'to_file';
1048
      $before_line_num = '';
added line number to commit ...
Yuki Kimoto authored on 2013-04-12
1049
      $after_line_num = $next_after_line_num++;
add diff status bar to commi...
Yuki Kimoto authored on 2013-05-30
1050
      $add_line_count++;
added line number logic to c...
Yuki Kimoto authored on 2013-04-12
1051
    }
fixed blob diff line number ...
Yuki Kimoto authored on 2013-06-01
1052
    elsif ($line =~ /^Binary files/) {
1053
      $class = 'binary_file';
1054
      $diff_info->{binary} = 1;
1055
    }
added line number logic to c...
Yuki Kimoto authored on 2013-04-12
1056
    elsif ($line =~ /^ /) {
1057
      $class = 'diff';
added line number to commit ...
Yuki Kimoto authored on 2013-04-12
1058
      $before_line_num = $next_before_line_num++;
1059
      $after_line_num = $next_after_line_num++;
added line number logic to c...
Yuki Kimoto authored on 2013-04-12
1060
    }
1061
    else { next }
cleanup commit page
Yuki Kimoto authored on 2013-04-12
1062
    
1063
    my $line_data = {
1064
      value => $line,
1065
      class => $class,
1066
      before_line_num => $before_line_num,
1067
      after_line_num => $after_line_num
1068
    };
1069
    push @lines, $line_data;
improved commit page design
Yuki Kimoto authored on 2013-04-12
1070
  }
1071
  
add diff status bar to commi...
Yuki Kimoto authored on 2013-05-30
1072
  # Diff info
1073
  my $diff_line_count = $add_line_count + $delete_line_count;
1074
  my $add_block_count
1075
    = $diff_line_count == 0
1076
    ? 0
1077
    : floor(($add_line_count * 5) / $diff_line_count);
1078
  my $delete_block_count
1079
    = $diff_line_count == 0
1080
    ? 0
1081
    : floor(($delete_line_count * 5) / $diff_line_count);
1082
  
fixed blob diff line number ...
Yuki Kimoto authored on 2013-06-01
1083
  $diff_info->{add_line_count} = $add_line_count;
1084
  $diff_info->{delete_line_count} = $delete_line_count;
1085
  $diff_info->{add_block_count} = $add_block_count;
1086
  $diff_info->{delete_block_count} = $delete_block_count;
1087
  
add diff status bar to commi...
Yuki Kimoto authored on 2013-05-30
1088
  return (\@lines, $diff_info);
improved commit page design
Yuki Kimoto authored on 2013-04-12
1089
}
1090

            
rename parse_commit to get_c...
Yuki Kimoto authored on 2013-05-01
1091
sub get_commit {
cleanup methods
Yuki Kimoto authored on 2016-04-16
1092
  my ($self, $rep_info, $id) = @_;
cleanup branch
Yuki Kimoto authored on 2016-04-16
1093
  
1094
  # Git rev-list
cleanup cmd
Yuki Kimoto authored on 2016-04-16
1095
  my @cmd = $self->cmd(
cleanup methods
Yuki Kimoto authored on 2016-04-16
1096
    $rep_info,
cleanup rep_info
Yuki Kimoto authored on 2016-04-16
1097
    'rev-list',
1098
    '--parents',
1099
    '--header',
1100
    '--max-count=1',
1101
    $id,
1102
    '--'
cleanup branch
Yuki Kimoto authored on 2016-04-16
1103
  );
1104
  open my $fh, '-|', @cmd
1105
    or croak 'Open git-rev-list failed';
1106
  
1107
  # Parse commit
1108
  local $/ = "\0";
1109
  my $content = <$fh>;
1110
  $content = $self->_dec($content);
1111
  return unless defined $content;
1112
  my $commit = $self->parse_commit_text($content, 1);
copy gitweblite soruce code
root authored on 2012-11-23
1113
  close $fh;
1114

            
1115
  return $commit;
1116
}
1117

            
1118
sub parse_commit_text {
1119
  my ($self, $commit_text, $withparents) = @_;
1120
  
1121
  my @commit_lines = split '\n', $commit_text;
1122
  my %commit;
1123

            
1124
  pop @commit_lines; # Remove '\0'
1125
  return unless @commit_lines;
1126

            
1127
  my $header = shift @commit_lines;
1128
  return if $header !~ m/^[0-9a-fA-F]{40}/;
1129
  
1130
  ($commit{id}, my @parents) = split ' ', $header;
1131
  while (my $line = shift @commit_lines) {
1132
    last if $line eq "\n";
1133
    if ($line =~ m/^tree ([0-9a-fA-F]{40})$/) {
1134
      $commit{tree} = $1;
1135
    } elsif ((!defined $withparents) && ($line =~ m/^parent ([0-9a-fA-F]{40})$/)) {
1136
      push @parents, $1;
1137
    } elsif ($line =~ m/^author (.*) ([0-9]+) (.*)$/) {
1138
      $commit{author} = $1;
1139
      $commit{author_epoch} = $2;
1140
      $commit{author_tz} = $3;
1141
      if ($commit{author} =~ m/^([^<]+) <([^>]*)>/) {
1142
        $commit{author_name}  = $1;
1143
        $commit{author_email} = $2;
1144
      } else {
1145
        $commit{author_name} = $commit{author};
1146
      }
1147
    } elsif ($line =~ m/^committer (.*) ([0-9]+) (.*)$/) {
1148
      $commit{committer} = $1;
1149
      $commit{committer_epoch} = $2;
1150
      $commit{committer_tz} = $3;
1151
      if ($commit{committer} =~ m/^([^<]+) <([^>]*)>/) {
1152
        $commit{committer_name}  = $1;
1153
        $commit{committer_email} = $2;
1154
      } else {
1155
        $commit{committer_name} = $commit{committer};
1156
      }
1157
    }
1158
  }
1159
  return unless defined $commit{tree};
1160
  $commit{parents} = \@parents;
1161
  $commit{parent} = $parents[0];
1162

            
1163
  for my $title (@commit_lines) {
1164
    $title =~ s/^    //;
1165
    if ($title ne '') {
1166
      $commit{title} = $self->_chop_str($title, 80, 5);
1167
      # remove leading stuff of merges to make the interesting part visible
1168
      if (length($title) > 50) {
1169
        $title =~ s/^Automatic //;
1170
        $title =~ s/^merge (of|with) /Merge ... /i;
1171
        if (length($title) > 50) {
1172
          $title =~ s/(http|rsync):\/\///;
1173
        }
1174
        if (length($title) > 50) {
1175
          $title =~ s/(master|www|rsync)\.//;
1176
        }
1177
        if (length($title) > 50) {
1178
          $title =~ s/kernel.org:?//;
1179
        }
1180
        if (length($title) > 50) {
1181
          $title =~ s/\/pub\/scm//;
1182
        }
1183
      }
1184
      $commit{title_short} = $self->_chop_str($title, 50, 5);
1185
      last;
1186
    }
1187
  }
1188
  if (! defined $commit{title} || $commit{title} eq '') {
1189
    $commit{title} = $commit{title_short} = '(no commit message)';
1190
  }
1191
  # remove added spaces
1192
  for my $line (@commit_lines) {
1193
    $line =~ s/^    //;
1194
  }
1195
  $commit{comment} = \@commit_lines;
1196

            
1197
  my $age = time - $commit{committer_epoch};
1198
  $commit{age} = $age;
1199
  $commit{age_string} = $self->_age_string($age);
add time zone system
Yuki Kimoto authored on 2014-03-08
1200
  
1201
  # GMT
1202
  {
support atom feed of commits...
Yuki Kimoto authored on 2014-10-03
1203
    my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($commit{committer_epoch});
add time zone system
Yuki Kimoto authored on 2014-03-08
1204
    $commit{age_string_date} = sprintf '%4d-%02d-%02d', 1900 + $year, $mon + 1, $mday;
1205
    $commit{age_string_datetime} = sprintf '%4d-%02d-%02d %02d:%02d:%02d',
1206
      1900 + $year, $mon + 1, $mday, $hour, $min, $sec;
1207
  }
1208
  
1209
  # Local Time
1210
  {
1211
    my $time_zone_second = $self->time_zone_second || 0;
1212
    
support atom feed of commits...
Yuki Kimoto authored on 2014-10-03
1213
    my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($commit{committer_epoch} + $time_zone_second);
add time zone system
Yuki Kimoto authored on 2014-03-08
1214
    $commit{age_string_date_local}
1215
      = sprintf '%4d-%02d-%02d', 1900 + $year, $mon + 1, $mday;
support atom feed of commits...
Yuki Kimoto authored on 2014-10-03
1216
    $commit{age_string_datetime_local} = sprintf '%4d-%02d-%02d %02d:%02d:%02d',
add time zone system
Yuki Kimoto authored on 2014-03-08
1217
      1900 + $year, $mon + 1, $mday, $hour, $min, $sec;
1218
  }
support atom feed of commits...
Yuki Kimoto authored on 2014-10-03
1219

            
copy gitweblite soruce code
root authored on 2012-11-23
1220
  return \%commit;
1221
}
1222

            
cleanup
Yuki Kimoto authored on 2013-04-30
1223
sub get_commits {
cleanup import_branch
Yuki Kimoto authored on 2016-04-16
1224
  my ($self, $rep_info, $rev, $maxcount, $skip, $file, @args) = @_;
copy gitweblite soruce code
root authored on 2012-11-23
1225

            
cleanup
Yuki Kimoto authored on 2013-03-19
1226
  # Get Commits
copy gitweblite soruce code
root authored on 2012-11-23
1227
  $maxcount ||= 1;
1228
  $skip ||= 0;
cleanup import_branch
Yuki Kimoto authored on 2016-04-16
1229
  my @cmd = $self->cmd(
1230
    $rep_info,
cleanup
Yuki Kimoto authored on 2013-03-19
1231
    'rev-list',
1232
    '--header',
1233
    @args,
1234
    ('--max-count=' . $maxcount),
1235
    ('--skip=' . $skip),
impved merge commit logic
Yuki Kimoto authored on 2013-06-01
1236
    $rev,
cleanup
Yuki Kimoto authored on 2013-03-19
1237
    '--',
added branch long name featu...
Yuki Kimoto authored on 2013-05-12
1238
    (defined $file && length $file ? ($file) : ())
cleanup
Yuki Kimoto authored on 2013-03-19
1239
  );
copy gitweblite soruce code
root authored on 2012-11-23
1240
  open my $fh, '-|', @cmd
1241
    or croak 'Open git-rev-list failed';
cleanup
Yuki Kimoto authored on 2013-03-19
1242
  
1243
  # Prase Commits text
copy gitweblite soruce code
root authored on 2012-11-23
1244
  local $/ = "\0";
1245
  my @commits;
cleanup encoding
Yuki Kimoto authored on 2016-04-05
1246
  my @lines = <$fh>;
1247
  for my $line (@lines) {
1248
    $line = $self->_dec($line);
copy gitweblite soruce code
root authored on 2012-11-23
1249
    my $commit = $self->parse_commit_text($line);
1250
    push @commits, $commit;
1251
  }
1252
  close $fh;
cleanup
Yuki Kimoto authored on 2013-03-19
1253
  
copy gitweblite soruce code
root authored on 2012-11-23
1254
  return \@commits;
1255
}
1256

            
1257
sub parse_date {
1258
  my $self = shift;
1259
  my $epoch = shift;
1260
  my $tz = shift || '-0000';
1261
  
1262
  # Parse data
1263
  my %date;
1264
  my @months = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/;
1265
  my @days = qw/Sun Mon Tue Wed Thu Fri Sat/;
1266
  my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime $epoch;
1267
  $date{hour} = $hour;
1268
  $date{minute} = $min;
1269
  $date{mday} = $mday;
1270
  $date{day} = $days[$wday];
1271
  $date{month} = $months[$mon];
1272
  $date{rfc2822} = sprintf '%s, %d %s %4d %02d:%02d:%02d +0000',
1273
    $days[$wday], $mday, $months[$mon], 1900 + $year, $hour ,$min, $sec;
1274
  $date{'mday-time'} = sprintf '%d %s %02d:%02d',
1275
    $mday, $months[$mon], $hour ,$min;
1276
  $date{'iso-8601'}  = sprintf '%04d-%02d-%02dT%02d:%02d:%02dZ',
1277
    1900 + $year, 1+$mon, $mday, $hour ,$min, $sec;
1278
  my ($tz_sign, $tz_hour, $tz_min) = ($tz =~ m/^([-+])(\d\d)(\d\d)$/);
1279
  $tz_sign = ($tz_sign eq '-' ? -1 : +1);
1280
  my $local = $epoch + $tz_sign * ((($tz_hour*60) + $tz_min) * 60);
1281
  ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime $local;
1282
  $date{hour_local} = $hour;
1283
  $date{minute_local} = $min;
1284
  $date{tz_local} = $tz;
1285
  $date{'iso-tz'} = sprintf('%04d-%02d-%02d %02d:%02d:%02d %s',
1286
    1900 + $year, $mon+1, $mday, $hour, $min, $sec, $tz);
1287
  
1288
  return \%date;
1289
}
1290

            
cleanup
Yuki Kimoto authored on 2013-05-14
1291
sub parsed_diff_tree_line {
copy gitweblite soruce code
root authored on 2012-11-23
1292
  my ($self, $line) = @_;
1293
  
1294
  return $line if ref $line eq 'HASH';
1295

            
cleanup
Yuki Kimoto authored on 2013-05-14
1296
  return $self->parse_diff_tree_line($line);
copy gitweblite soruce code
root authored on 2012-11-23
1297
}
1298

            
cleanup
Yuki Kimoto authored on 2013-05-14
1299
sub parse_diff_tree_line {
copy gitweblite soruce code
root authored on 2012-11-23
1300
  my ($self, $line) = @_;
1301

            
1302
  my %res;
1303
  if ($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/) {
1304
    $res{from_mode} = $1;
1305
    $res{to_mode} = $2;
1306
    $res{from_id} = $3;
1307
    $res{to_id} = $4;
1308
    $res{status} = $5;
1309
    $res{similarity} = $6;
1310
    if ($res{status} eq 'R' || $res{status} eq 'C') {
1311
      ($res{from_file}, $res{to_file}) = map { $self->_unquote($_) } split("\t", $7);
1312
    } else {
1313
      $res{from_file} = $res{to_file} = $res{file} = $self->_unquote($7);
1314
    }
1315
  }
1316
  elsif ($line =~ s/^(::+)((?:[0-7]{6} )+)((?:[0-9a-fA-F]{40} )+)([a-zA-Z]+)\t(.*)$//) {
1317
    $res{nparents}  = length($1);
1318
    $res{from_mode} = [ split(' ', $2) ];
1319
    $res{to_mode} = pop @{$res{from_mode}};
1320
    $res{from_id} = [ split(' ', $3) ];
1321
    $res{to_id} = pop @{$res{from_id}};
1322
    $res{status} = [ split('', $4) ];
1323
    $res{to_file} = $self->_unquote($5);
1324
  }
1325
  elsif ($line =~ m/^([0-9a-fA-F]{40})$/) { $res{commit} = $1 }
1326

            
1327
  return \%res;
1328
}
1329

            
1330
sub parse_ls_tree_line {
1331
  my ($self, $line) = @_;
1332
  my %opts = @_;
1333
  my %res;
1334

            
1335
  if ($opts{'-l'}) {
1336
    $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40}) +(-|[0-9]+)\t(.+)$/s;
1337

            
1338
    $res{mode} = $1;
1339
    $res{type} = $2;
1340
    $res{hash} = $3;
1341
    $res{size} = $4;
1342
    if ($opts{'-z'}) { $res{name} = $5 }
1343
    else { $res{name} = $self->_unquote($5) }
1344
  }
1345
  else {
1346
    $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/s;
1347

            
1348
    $res{mode} = $1;
1349
    $res{type} = $2;
1350
    $res{hash} = $3;
1351
    if ($opts{'-z'}) { $res{name} = $4 }
1352
    else { $res{name} = $self->_unquote($4) }
1353
  }
1354

            
1355
  return \%res;
1356
}
1357

            
change pull feature to impor...
Yuki Kimoto authored on 2013-08-14
1358
sub import_branch {
cleanup import_branch
Yuki Kimoto authored on 2016-04-16
1359
  my ($self, $rep_info, $branch, $remote_rep_info, $remote_branch, $opt) = @_;
complete branch import featu...
Yuki Kimoto authored on 2013-08-15
1360
  
1361
  my $force = $opt->{force};
change pull feature to impor...
Yuki Kimoto authored on 2013-08-14
1362
  
1363
  # Git pull
cleanup import_branch
Yuki Kimoto authored on 2016-04-16
1364
  my $remote_rep = $remote_rep_info->{git_dir};
1365
  my @cmd = $self->cmd(
1366
    $rep_info,
change pull feature to impor...
Yuki Kimoto authored on 2013-08-14
1367
    'fetch',
1368
    $remote_rep,
complete branch import featu...
Yuki Kimoto authored on 2013-08-15
1369
    ($force ? '+' : '') . "refs/heads/$remote_branch:refs/heads/$branch"
change pull feature to impor...
Yuki Kimoto authored on 2013-08-14
1370
  );
1371
  
fix bug that in CGI reposito...
Yuki Kimoto authored on 2015-11-05
1372
  Gitprep::Util::run_command(@cmd)
complete branch import featu...
Yuki Kimoto authored on 2013-08-15
1373
    or croak 'Open git fetch for import_branch failed';
change pull feature to impor...
Yuki Kimoto authored on 2013-08-14
1374
}
1375

            
copy gitweblite soruce code
root authored on 2012-11-23
1376
sub search_bin {
1377
  my $self = shift;
1378
  
1379
  # Search git bin
1380
  my $env_path = $ENV{PATH};
1381
  my @paths = split /:/, $env_path;
1382
  for my $path (@paths) {
1383
    $path =~ s#/$##;
1384
    my $bin = "$path/git";
1385
    if (-f $bin) {
1386
      return $bin;
1387
      last;
1388
    }
1389
  }
improved git path searching
Yuki Kimoto authored on 2012-11-23
1390
  
1391
  my $local_bin = '/usr/local/bin/git';
1392
  return $local_bin if -f $local_bin;
1393
  
1394
  my $bin = '/usr/bin/git';
1395
  return $bin if -f $bin;
1396
  
copy gitweblite soruce code
root authored on 2012-11-23
1397
  return;
1398
}
1399

            
improved create repository f...
Yuki Kimoto authored on 2013-03-21
1400
sub separated_commit {
cleanup methods
Yuki Kimoto authored on 2016-04-16
1401
  my ($self, $rep_info, $rev1, $rev2) = @_;
improved create repository f...
Yuki Kimoto authored on 2013-03-21
1402
  
1403
  # Command "git diff-tree"
cleanup methods
Yuki Kimoto authored on 2016-04-16
1404
  my @cmd = $self->cmd(
1405
    $rep_info,
improved create repository f...
Yuki Kimoto authored on 2013-03-21
1406
    'show-branch',
1407
    $rev1,
1408
    $rev2
1409
  );
1410
  open my $fh, "-|", @cmd
1411
    or croak 500, "Open git-show-branch failed";
1412

            
1413
  my $commits = [];
1414
  my $start;
1415
  my @lines = <$fh>;
1416
  my $last_line = pop @lines;
1417
  my $commit;
1418
  if (defined $last_line) {
1419
      my ($id) = $last_line =~ /^.*?\[(.+)?\]/;
cleanup methods
Yuki Kimoto authored on 2016-04-16
1420
      $commit = $self->get_commit($rep_info, $id);
improved create repository f...
Yuki Kimoto authored on 2013-03-21
1421
  }
1422

            
1423
  return $commit;
1424
}
1425

            
copy gitweblite soruce code
root authored on 2012-11-23
1426
sub snapshot_name {
impved merge commit logic
Yuki Kimoto authored on 2013-06-01
1427
  my ($self, $project, $rev) = @_;
copy gitweblite soruce code
root authored on 2012-11-23
1428

            
1429
  my $name = $project;
1430
  $name =~ s,([^/])/*\.git$,$1,;
1431
  $name = basename($name);
1432
  # sanitize name
1433
  $name =~ s/[[:cntrl:]]/?/g;
1434

            
impved merge commit logic
Yuki Kimoto authored on 2013-06-01
1435
  my $ver = $rev;
1436
  if ($rev =~ /^[0-9a-fA-F]+$/) {
1437
    my $full_hash = $self->id($project, $rev);
1438
    if ($full_hash =~ /^$rev/ && length($rev) > 7) {
1439
      $ver = $self->short_id($project, $rev);
copy gitweblite soruce code
root authored on 2012-11-23
1440
    }
impved merge commit logic
Yuki Kimoto authored on 2013-06-01
1441
  } elsif ($rev =~ m!^refs/tags/(.*)$!) {
copy gitweblite soruce code
root authored on 2012-11-23
1442
    $ver = $1;
1443
  } else {
impved merge commit logic
Yuki Kimoto authored on 2013-06-01
1444
    if ($rev =~ m!^refs/(?:heads|remotes)/(.*)$!) {
copy gitweblite soruce code
root authored on 2012-11-23
1445
      $ver = $1;
1446
    }
impved merge commit logic
Yuki Kimoto authored on 2013-06-01
1447
    $ver .= '-' . $self->short_id($project, $rev);
copy gitweblite soruce code
root authored on 2012-11-23
1448
  }
1449
  $ver =~ s!/!.!g;
1450

            
1451
  $name = "$name-$ver";
1452

            
1453
  return wantarray ? ($name, $name) : $name;
1454
}
1455

            
change pull feature to impor...
Yuki Kimoto authored on 2013-08-14
1456
sub timestamp {
1457
  my ($self, $date) = @_;
1458
  
1459
  # Time stamp
1460
  my $strtime = $date->{rfc2822};
1461
  my $localtime_format = '(%02d:%02d %s)';
1462
  if ($date->{hour_local} < 6) { $localtime_format = '(%02d:%02d %s)' }
1463
  $strtime .= ' ' . sprintf(
1464
    $localtime_format,
1465
    $date->{hour_local},
1466
    $date->{minute_local},
1467
    $date->{tz_local}
1468
  );
1469

            
1470
  return $strtime;
1471
}
1472

            
1473
sub trees {
cleanup methods
Yuki Kimoto authored on 2016-04-16
1474
  my ($self, $rep_info, $rev, $dir) = @_;
change pull feature to impor...
Yuki Kimoto authored on 2013-08-14
1475
  $dir = '' unless defined $dir;
1476
  
1477
  # Get tree
1478
  my $tid;
1479
  if (defined $dir && $dir ne '') {
cleanup methods
Yuki Kimoto authored on 2016-04-16
1480
    $tid = $self->path_to_hash($rep_info, $rev, $dir, 'tree');
change pull feature to impor...
Yuki Kimoto authored on 2013-08-14
1481
  }
1482
  else {
cleanup methods
Yuki Kimoto authored on 2016-04-16
1483
    my $commit = $self->get_commit($rep_info, $rev);
change pull feature to impor...
Yuki Kimoto authored on 2013-08-14
1484
    $tid = $commit->{tree};
1485
  }
1486
  my @entries = ();
1487
  my $show_sizes = 0;
cleanup methods
Yuki Kimoto authored on 2016-04-16
1488
  my @cmd = $self->cmd(
1489
    $rep_info,
change pull feature to impor...
Yuki Kimoto authored on 2013-08-14
1490
    'ls-tree',
1491
    '-z',
1492
    ($show_sizes ? '-l' : ()),
1493
    $tid
1494
  );
1495
  open my $fh, '-|', @cmd
1496
    or $self->croak('Open git-ls-tree failed');
1497
  {
1498
    local $/ = "\0";
cleanup encoding
Yuki Kimoto authored on 2016-04-05
1499
    @entries = <$fh>;
1500
    @entries = map { chomp; $self->_dec($_) } @entries;
change pull feature to impor...
Yuki Kimoto authored on 2013-08-14
1501
  }
1502
  close $fh
1503
    or $self->croak(404, "Reading tree failed");
1504

            
1505
  # Parse tree
1506
  my $trees;
1507
  for my $line (@entries) {
1508
    my $tree = $self->parse_ls_tree_line($line, -z => 1, -l => $show_sizes);
1509
    $tree->{mode_str} = $self->_mode_str($tree->{mode});
1510
    
1511
    # Commit log
1512
    my $path = defined $dir && $dir ne '' ? "$dir/$tree->{name}" : $tree->{name};
cleanup methods
Yuki Kimoto authored on 2016-04-16
1513
    my $commit = $self->last_change_commit($rep_info, $rev, $path);
change pull feature to impor...
Yuki Kimoto authored on 2013-08-14
1514
    $tree->{commit} = $commit;
1515
    
1516
    push @$trees, $tree;
1517
  }
1518
  $trees = [sort {$b->{type} cmp $a->{type} || $a->{name} cmp $b->{name}} @$trees];
1519
  
1520
  return $trees;
1521
}
1522

            
refactored
Xavier Caron authored on 2013-08-30
1523
sub _age_ago {
1524
  my($self,$unit,$age) = @_;
1525

            
does not use plural when uni...
Xavier Caron authored on 2013-08-30
1526
  return $age . " $unit" . ( $unit =~ /^(sec|min)$/ ? "" : ( $age > 1 ? "s" : "" ) ) . " ago";
refactored
Xavier Caron authored on 2013-08-30
1527
}
1528

            
copy gitweblite soruce code
root authored on 2012-11-23
1529
sub _age_string {
1530
  my ($self, $age) = @_;
1531
  my $age_str;
1532

            
added commit datetime to pro...
Yuki Kimoto authored on 2013-05-03
1533
  if ($age >= 60 * 60 * 24 * 365) {
refactored
Xavier Caron authored on 2013-08-30
1534
    $age_str = $self->_age_ago(year => (int $age/60/60/24/365));
added commit datetime to pro...
Yuki Kimoto authored on 2013-05-03
1535
  } elsif ($age >= 60 * 60 * 24 * (365/12)) {
refactored
Xavier Caron authored on 2013-08-30
1536
    $age_str = $self->_age_ago(month => int $age/60/60/24/(365/12));
added commit datetime to pro...
Yuki Kimoto authored on 2013-05-03
1537
  } elsif ($age >= 60 * 60 * 24 * 7) {
refactored
Xavier Caron authored on 2013-08-30
1538
    $age_str = $self->_age_ago(week => int $age/60/60/24/7);
added commit datetime to pro...
Yuki Kimoto authored on 2013-05-03
1539
  } elsif ($age >= 60 * 60 * 24) {
refactored
Xavier Caron authored on 2013-08-30
1540
    $age_str = $self->_age_ago(day => int $age/60/60/24);
added commit datetime to pro...
Yuki Kimoto authored on 2013-05-03
1541
  } elsif ($age >= 60 * 60) {
refactored
Xavier Caron authored on 2013-08-30
1542
    $age_str = $self->_age_ago(hour => int $age/60/60);
added commit datetime to pro...
Yuki Kimoto authored on 2013-05-03
1543
  } elsif ($age >= 60) {
refactored
Xavier Caron authored on 2013-08-30
1544
    $age_str = $self->_age_ago(min => int $age/60);
added commit datetime to pro...
Yuki Kimoto authored on 2013-05-03
1545
  } elsif ($age >= 1) {
refactored
Xavier Caron authored on 2013-08-30
1546
    $age_str = $self->_age_ago(sec => int $age);
copy gitweblite soruce code
root authored on 2012-11-23
1547
  } else {
fixed a typo
Xavier Caron authored on 2013-08-30
1548
    $age_str .= 'right now';
copy gitweblite soruce code
root authored on 2012-11-23
1549
  }
cleanup blob and raw page
Yuki Kimoto authored on 2013-05-02
1550
  
1551
  $age_str =~ s/^1 /a /;
more phonetically correct
Xavier Caron authored on 2013-08-30
1552
  $age_str =~ s/^a hour/an hour/;
cleanup blob and raw page
Yuki Kimoto authored on 2013-05-02
1553
  
copy gitweblite soruce code
root authored on 2012-11-23
1554
  return $age_str;
1555
}
1556

            
1557
sub _chop_str {
1558
  my $self = shift;
1559
  my $str = shift;
1560
  my $len = shift;
1561
  my $add_len = shift || 10;
1562
  my $where = shift || 'right';
1563

            
1564
  if ($where eq 'center') {
1565
    # Filler is length 5
1566
    return $str if ($len + 5 >= length($str));
1567
    $len = int($len/2);
1568
  } else {
1569
    # Filler is length 4
1570
    return $str if ($len + 4 >= length($str)); 
1571
  }
1572

            
1573
  # Regexps: ending and beginning with word part up to $add_len
1574
  my $endre = qr/.{$len}\w{0,$add_len}/;
1575
  my $begre = qr/\w{0,$add_len}.{$len}/;
1576

            
1577
  if ($where eq 'left') {
1578
    $str =~ m/^(.*?)($begre)$/;
1579
    my ($lead, $body) = ($1, $2);
1580
    if (length($lead) > 4) {
1581
      $lead = ' ...';
1582
    }
1583
    return "$lead$body";
1584

            
1585
  } elsif ($where eq 'center') {
1586
    $str =~ m/^($endre)(.*)$/;
1587
    my ($left, $str)  = ($1, $2);
1588
    $str =~ m/^(.*?)($begre)$/;
1589
    my ($mid, $right) = ($1, $2);
1590
    if (length($mid) > 5) {
1591
      $mid = ' ... ';
1592
    }
1593
    return "$left$mid$right";
1594

            
1595
  } else {
1596
    $str =~ m/^($endre)(.*)$/;
1597
    my $body = $1;
1598
    my $tail = $2;
1599
    if (length($tail) > 4) {
1600
      $tail = '... ';
1601
    }
1602
    return "$body$tail";
1603
  }
1604
}
1605

            
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
1606
sub decide_encoding {
cleanup methods
Yuki Kimoto authored on 2016-04-16
1607
  my ($self, $rep_info, $lines) = @_;
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
1608
  
1609
  my $guess_encoding_str = $self->app->dbi->model('project')->select(
1610
    'guess_encoding',
cleanup methods
Yuki Kimoto authored on 2016-04-16
1611
    where => {user_id => $rep_info->{user}, name => $rep_info->{project}}
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
1612
  )->value;
cleanup encoding_suspects
Yuki Kimoto authored on 2016-04-05
1613
  
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
1614
  my @guess_encodings;
cleanup blame
Yuki Kimoto authored on 2016-04-16
1615
  if (defined $guess_encoding_str && length $guess_encoding_str) {
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
1616
    @guess_encodings = split(/\s*,\s*/, $guess_encoding_str);
1617
  }
cleanup encoding_suspects
Yuki Kimoto authored on 2016-04-05
1618
  
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
1619
  my $encoding;
1620
  if (@guess_encodings) {
1621
    my @new_lines;
1622
    for (my $i = 0; $i < 100; $i++) {
1623
      last unless defined $lines->[$i];
1624
      push @new_lines, $lines->[$i];
1625
    }
1626
    
1627
    my $str = join('', @new_lines);
1628

            
1629
    my $ret = Encode::Guess->guess($str, @guess_encodings);
1630
    
improve dec_guess logic
Yuki Kimoto authored on 2016-04-05
1631
    if (ref $ret) {
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
1632
      $encoding = $ret->name;
improve dec_guess logic
Yuki Kimoto authored on 2016-04-05
1633
    }
1634
    else {
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
1635
      $encoding = $self->default_encoding
cleanup encoding_suspects
Yuki Kimoto authored on 2016-04-05
1636
    }
1637
  }
1638
  else {
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
1639
    $encoding = $self->default_encoding;
cleanup encoding_suspects
Yuki Kimoto authored on 2016-04-05
1640
  }
1641
  
remove [basic]encoding_suspe...
Yuki Kimoto authored on 2016-04-06
1642
  return $encoding;
Supported specific character...
Tetsuya Hayashi authored on 2014-03-15
1643
}
1644

            
cleanuP
Yuki Kimoto authored on 2016-04-16
1645
sub _age_string_date {
1646
  my ($self, $age) = @_;
1647

            
1648
  my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($age);
1649
  my $age_string_date = sprintf '%4d-%02d-%02d', 1900 + $year, $mon + 1, $mday;
1650
  
1651
  return $age_string_date;
1652
}
1653

            
1654
sub _age_string_date_local {
1655
  my ($self, $age) = @_;
1656
  
1657
  my $time_zone_second = $self->time_zone_second || 0;
1658
  
1659
  my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($age + $time_zone_second);
1660
  my $age_string_date_local = sprintf '%4d-%02d-%02d', 1900 + $year, $mon + 1, $mday;
1661
  
1662
  return $age_string_date_local;
1663
}
1664

            
cleanup
Yuki Kimoto authored on 2013-05-14
1665
sub _dec {
revert encoding support
Yuki Kimoto authored on 2013-11-22
1666
  my ($self, $str) = @_;
improved create repository f...
Yuki Kimoto authored on 2013-03-21
1667
  
Renamed encoding to default_...
Tetsuya Hayashi authored on 2014-03-15
1668
  my $enc = $self->default_encoding;
improved create repository f...
Yuki Kimoto authored on 2013-03-21
1669
  
cleanup encoding logic
Yuki Kimoto authored on 2016-04-05
1670
  $str = decode($enc, $str);
improved create repository f...
Yuki Kimoto authored on 2013-03-21
1671
  
cleanup encoding logic
Yuki Kimoto authored on 2016-04-05
1672
  return $str;
added README commited rep fe...
Yuki Kimoto authored on 2013-03-28
1673
}
1674

            
revert encoding support
Yuki Kimoto authored on 2013-11-22
1675
sub _enc {
1676
  my ($self, $str) = @_;
1677
  
Renamed encoding to default_...
Tetsuya Hayashi authored on 2014-03-15
1678
  my $enc = $self->default_encoding;
revert encoding support
Yuki Kimoto authored on 2013-11-22
1679
  
1680
  return encode($enc, $str);
1681
}
1682

            
improved create repository f...
Yuki Kimoto authored on 2013-03-21
1683
sub _mode_str {
1684
  my $self = shift;
1685
  my $mode = oct shift;
1686

            
1687
  # Mode to string
1688
  if ($self->_s_isgitlink($mode)) { return 'm---------' }
1689
  elsif (S_ISDIR($mode & S_IFMT)) { return 'drwxr-xr-x' }
1690
  elsif (S_ISLNK($mode)) { return 'lrwxrwxrwx' }
1691
  elsif (S_ISREG($mode)) {
1692
    if ($mode & S_IXUSR) {
1693
      return '-rwxr-xr-x';
1694
    } else {
1695
      return '-rw-r--r--'
1696
    }
1697
  } else { return '----------' }
1698
  
1699
  return;
1700
}
1701

            
1702
sub _s_isgitlink {
1703
  my ($self, $mode) = @_;
1704
  
1705
  # Check if git link
1706
  my $s_ifgitlink = 0160000;
1707
  return (($mode & S_IFMT) == $s_ifgitlink)
copy gitweblite soruce code
root authored on 2012-11-23
1708
}
1709

            
1710
sub _slurp {
1711
  my ($self, $file) = @_;
1712
  
1713
  # Slurp
1714
  open my $fh, '<', $file
1715
    or croak qq/Can't open file "$file": $!/;
cleanup
Yuki Kimoto authored on 2013-11-16
1716
  my $content = do { local $/; scalar <$fh> };
copy gitweblite soruce code
root authored on 2012-11-23
1717
  close $fh;
1718
  
1719
  return $content;
1720
}
1721

            
1722
sub _unquote {
1723
  my ($self, $str) = @_;
1724
  
1725
  # Unquote function
1726
  my $unq = sub {
1727
    my $seq = shift;
1728
    my %escapes = (
1729
      t => "\t",
1730
      n => "\n",
1731
      r => "\r",
1732
      f => "\f",
1733
      b => "\b",
1734
      a => "\a",
1735
      e => "\e",
1736
      v => "\013",
1737
    );
1738

            
1739
    if ($seq =~ m/^[0-7]{1,3}$/) { return chr oct $seq }
1740
    elsif (exists $escapes{$seq}) { return $escapes{$seq} }
1741
    
1742
    return $seq;
1743
  };
1744
  
1745
  # Unquote
1746
  if ($str =~ m/^"(.*)"$/) {
1747
    $str = $1;
1748
    $str =~ s/\\([^0-7]|[0-7]{1,3})/$unq->($1)/eg;
1749
  }
1750
  
1751
  return $str;
1752
}
1753

            
1754
1;