source: trunk/project-meta/project-meta @ 178

Last change on this file since 178 was 178, checked in by g7moreau, 6 years ago
  • Add make-zip method
  • Property svn:executable set to *
File size: 11.6 KB
Line 
1#!/usr/bin/env perl
2#
3# 2018/01/17 Gabriel Moreau
4#
5# apt-get install yamllint libyaml-syck-perl libtemplate-perl
6
7use strict;
8use warnings;
9
10use File::Copy qw{copy};   
11use YAML::Syck;
12use Getopt::Long();
13use Cwd();
14use Template;
15
16
17my ($verbose);
18Getopt::Long::GetOptions(
19   'verbose' => \$verbose,
20   );
21
22
23my %CMD_DB = (
24   'help'            => \&cmd_help,
25   'version'         => \&cmd_version,
26   'check'           => \&cmd_check,
27   'make-link'       => \&cmd_make_link,
28   'make-zip'        => \&cmd_make_zip,
29   'make-author'     => \&cmd_make_author,
30   'make-licence'    => \&cmd_make_licence,
31   'make-copyright'  => \&cmd_make_copyright,
32   'list-licence'    => \&cmd_list_licence,
33   );
34
35################################################################
36# main program
37################################################################
38
39my $cmd = shift @ARGV || 'help';
40if (defined $CMD_DB{$cmd}) {
41   $CMD_DB{$cmd}->(@ARGV);
42   }
43else {
44   print {*STDERR} "project-meta: command $cmd not found\n\n";
45   $CMD_DB{'help'}->();
46   exit 1;
47   }
48
49exit;
50
51################################################################
52# subroutine
53################################################################
54
55################################################################
56# command
57################################################################
58
59sub cmd_help {
60   print <<'END';
61project-meta - opendata project metafile manager
62
63 project-meta help
64 project-meta version
65 project-meta check
66 project-meta make-link
67 project-meta make-author
68 project-meta make-licence
69 project-meta make-copyright
70 project-meta make-licence
71 project-meta list-licence
72END
73   }
74
75################################################################
76
77sub cmd_version {
78   print "0.0.2\n";
79   }
80
81################################################################
82
83sub print_ok {
84   my ($key, $test) = @_;
85   
86   printf "%-35s : %s\n", $key, $test ? 'yes' : 'no';
87   }
88
89################################################################
90
91sub cmd_check {
92   my $meta = YAML::Syck::LoadFile("PROJECT-META.yml");
93
94   my $acronym     = $meta->{'project'}{'acronym'};
95   my $current_dir = Cwd::getcwd();
96   my $dap_folder  = $meta->{'public-dap'}{'dap-folder'};
97
98   print_ok 'project/acronym',                  $acronym =~ m{\d\d\w[\w\d_]+};
99   print_ok 'public-dap/dap-folder',            $dap_folder ne '' and $dap_folder =~ m{^/};
100   print_ok 'dap-folder not match current_dir', $dap_folder !~ m{$current_dir};
101
102   #print YAML::Syck::Dump($meta);
103   }
104
105################################################################
106
107sub addfolder2list {
108   my ($folderdb, $folder) = @_;
109   
110   $folder =~ s{/[^/]+$}{};
111   
112   return if $folder !~ m{/};
113
114   $folderdb->{$folder}++;
115   return addfolder2list($folderdb, $folder);
116   }
117
118################################################################
119
120sub cmd_make_link {
121   my $meta = YAML::Syck::LoadFile("PROJECT-META.yml");
122   my $current_dir = Cwd::getcwd();
123   my $acronym     = $meta->{'project'}{'acronym'};
124   my $dap_folder  = $meta->{'public-dap'}{'dap-folder'};
125   my $data_set    = $meta->{'public-dap'}{'data-set'};
126
127   push @{$data_set}, 'AUTHORS.txt', 'COPYRIGHT.txt', 'LICENCE.txt';
128   {
129      # Remove doublon
130      my %seen = ();
131      @{$data_set} = grep { ! $seen{$_}++ } @{$data_set};
132      }
133
134   # Create a list of the folder
135   my %folders;
136   for my $dataset (@{$data_set}) {
137      addfolder2list(\%folders, $dataset);
138      }
139
140   print "chmod o+rX,o-w $current_dir\n";
141   print "mkdir -p $dap_folder/$acronym\n" if not -d "$dap_folder/$acronym";
142   for my $folder (sort keys %folders) {
143      print "chmod o+rX,o-w $current_dir/$folder\n";
144      print "mkdir -p $dap_folder/$acronym/$folder\n" if -d "$current_dir/$folder";
145      }
146
147   for my $dataset (@{$data_set}) {
148      if ($dataset =~ m{/}) {
149         # Folder case
150         my $folder = $dataset =~ s{/[^/]+$}{}r;
151         print "ln --symbolic --target-directory $dap_folder/$acronym/$folder/ $current_dir/$dataset\n";
152         }
153      else {
154         # File case
155         print "ln --symbolic --target-directory $dap_folder/$acronym/ $current_dir/$dataset\n";
156         }
157
158      }
159   print "chmod -R o+rX,o-w $dap_folder/$acronym/\n";
160   }
161
162################################################################
163
164sub cmd_make_zip {
165   my $meta = YAML::Syck::LoadFile("PROJECT-META.yml");
166   my $current_dir = Cwd::getcwd();
167   my $data_set    = $meta->{'public-dap'}{'data-set'};
168   my $acronym     = $meta->{'project'}{'acronym'};
169   my $time = time;
170
171   push @{$data_set}, 'AUTHORS.txt', 'COPYRIGHT.txt', 'LICENCE.txt';
172   {
173      # Remove doublon
174      my %seen = ();
175      @{$data_set} = grep { ! $seen{$_}++ } @{$data_set};
176      }
177
178   # Create a Zip file
179   use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
180
181   my $zip = Archive::Zip->new();
182
183   for my $dataset (@{$data_set}) {
184      if (-d $dataset) {
185         # Folder case
186         $zip->addDirectory($dataset);
187         }
188      elsif (-f $dataset) {
189         # File case
190         $zip->addFile($dataset);
191         }
192      else {
193         # Strange cas
194         print "Error: entry $dataset doesn't exists\n";
195         }
196      }
197
198   # Save the Zip file
199   unless ($zip->writeToFileNamed("$current_dir/$acronym-$time.zip") == AZ_OK) {
200      die 'Error: zip write error';
201      }
202   }
203
204################################################################
205
206sub cmd_make_author {
207   my $meta = YAML::Syck::LoadFile("PROJECT-META.yml");
208
209   my $current_dir = Cwd::getcwd();
210
211   my $acronym    = $meta->{'project'}{'acronym'};
212   my $authors_list = $meta->{'project'}{'authors'};
213
214   if (-f "$current_dir/AUTHORS.txt") {
215      # Test for manual or automatically generated file
216      # Automatically generated file by project-meta
217      my $automatic;
218      open my $fh, '<', "$current_dir/AUTHORS.txt" or die $!;
219      for my $line (<$fh>) {
220         $line =~ m/Automatically generated .* project-meta/i and $automatic++;
221         }
222      close $fh;
223
224      if (not $automatic) {
225         print "Warning: AUTHORS.txt already exists\n";
226         return;
227         }
228
229      print "Warning: update AUTHORS.txt\n";
230      }
231
232   my $tt = Template->new(INCLUDE_PATH => '/usr/share/project-meta/template.d');
233   my $msg_format = '';
234   $tt->process('AUTHORS.tt',
235      {
236         acronym    => $acronym,
237         authorlist => $authors_list,
238      }, \$msg_format) || die $tt->error;
239
240   open my $fh,  '>', "$current_dir/AUTHORS.txt" or die $!;
241   print $fh "$msg_format\n\n";
242   close $fh;
243   }
244
245################################################################
246
247sub cmd_make_licence {
248   my $meta = YAML::Syck::LoadFile("PROJECT-META.yml");
249
250   my $current_dir = Cwd::getcwd();
251
252   if (-f "$current_dir/LICENCE.txt") {
253      print "Warning: LICENCE.txt already exists\n";
254      return;
255      }
256
257   my $licence = $meta->{'public-dap'}{'data-licence'};
258
259   if (not -f "/usr/share/project-meta/licence.d/$licence.txt") {
260      print "Error: licence $licence doesn't exists in project-meta database\n";
261      exit 1;
262      }
263
264   copy("/usr/share/project-meta/licence.d/$licence.txt", "$current_dir/LICENCE.txt")
265      or die "Error: licence copy failed - $!";
266
267   print "Info: LICENCE.txt file create\n";
268   return;
269   }
270
271################################################################
272
273sub cmd_make_copyright {
274   my $meta = YAML::Syck::LoadFile("PROJECT-META.yml");
275
276   my $current_dir = Cwd::getcwd();
277
278   if (-f "$current_dir/COPYRIGHT.txt") {
279      # Test for manual or automatically generated file
280      # Automatically generated file by project-meta
281      my $automatic;
282      open my $fh, '<', "$current_dir/COPYRIGHT.txt" or die $!;
283      for my $line (<$fh>) {
284         $line =~ m/Automatically generated .* project-meta/i and $automatic++;
285         }
286      close $fh;
287
288      if (not $automatic) {
289         print "Warning: COPYRIGHT.txt already exists\n";
290         return;
291         }
292
293      print "Warning: update COPYRIGHT.txt\n";
294      }
295   
296   my $tt = Template->new(
297      INCLUDE_PATH   => '/usr/share/project-meta/template.d',
298      POST_CHOMP     => 1, # Remove space and carriage return after %]
299      );
300   my $msg_format = '';
301   $tt->process('COPYRIGHT.tt',
302      {
303         title       => $meta->{'project'}{'title'},
304         acronym     => $meta->{'project'}{'acronym'},
305         authorlist  => $meta->{'project'}{'authors'},
306         description => $meta->{'project'}{'short-description'},
307         licence     => $meta->{'public-dap'}{'data-licence'},
308         doi         => $meta->{'publication'}{'doi'},
309      }, \$msg_format) || die $tt->error;
310
311   open my $fh,  '>', "$current_dir/COPYRIGHT.txt" or die $!;
312   print $fh "$msg_format\n\n";
313   close $fh;
314   }
315
316################################################################
317
318sub cmd_list_licence {
319   opendir my $dh, '/usr/share/project-meta/licence.d/' or die $!;
320   for my $licence (readdir $dh) {
321      # Keep only file
322      next if not -f "/usr/share/project-meta/licence.d/$licence";
323     
324      # Keep only .txt file
325      next if not $licence =~ m/\.txt$/;
326
327      $licence =~ s/\.txt$//;
328      print "$licence\n";
329      }
330   closedir $dh;
331   }
332
333################################################################
334# documentation
335################################################################
336
337__END__
338
339=head1 NAME
340
341project-meta - opendata project metafile manager
342
343
344=head1 USAGE
345
346 project-meta help
347 project-meta version
348 project-meta check
349 project-meta make-link
350 project-meta make-author
351 project-meta make-licence
352 project-meta make-copyright
353 project-meta make-licence
354 project-meta list-licence
355
356=head1 DESCRIPTION
357
358project-meta is a small tool to maintain a set of open data files.
359
360=head1 COMMANDS
361
362Some command are defined in the source code but are not documented here.
363Theses could be not well defined, not finished, not well tested...
364You can read the source code and use them at your own risk
365(like for all the Klask code).
366
367=head2 check
368
369 project-meta check
370
371Check your F<PROJECT-META.yml> has the good key.
372If your metafile is not a valid YAML file,
373you can use C<yamllint> command to check just it's format.
374
375=head2 make-licence
376
377 project-meta make-licence
378
379Copy the licence file from the project-meta licence database at the current folder with the file name: LICENCE.txt.
380
381The licence is defined in the PROJECT-META.yml specification under the key C<public-dap/data-licence>.
382The list of possible licence is given with the command L<list-licence>.
383
384=head2 list-licence
385
386 project-meta list-licence
387
388Give the list of all the open data licence supported by the project-meta licence database.
389At this time the possible licence are:
390
391 license-ouverte-v2.0
392 open-database-license-v1.0
393
394
395=head1 METAFILE SPECIFICATION
396
397Each project must have an open data metafile which describe the project : C<PROJECT-META.yml>.
398The file is in YAML format because this is a human readable style of text file.
399
400You can find in the project-meta software a C<PROJECT-META.sample.yml> example.
401This one is actually the master reference specification!
402
403
404=head1 BUG
405
406 - make-link: folder/folder
407 - make-link: support multiple doi
408 - metafile: remove prop publication/url
409
410=head1 SEE ALSO
411
412yamllint
413
414
415=head1 AUTHOR
416
417Written by Gabriel Moreau, LEGI UMR5519, CNRS, Grenoble - France
418
419=head1 SPECIAL THANKS
420
421The list of people below did not directly contribute to project-meta's source code
422but provided me with some data, returned bugs
423or helped me in another small task like having new ideas ...
424Maybe I forgot your contribution in recent years,
425please forgive me in advance and send me an e-mail to correct this.
426
427Joel Sommeria, Julien Chauchat, Cyrille Bonamy, Antoine Mathieu.
428
429
430=head1 LICENSE AND COPYRIGHT
431
432Licence GNU GPL version 2 or later and Perl equivalent
433
434Copyright (C) 2017-2018 Gabriel Moreau <Gabriel.Moreau(A)univ-grenoble-alpes.fr>.
Note: See TracBrowser for help on using the repository browser.