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

Last change on this file since 182 was 182, checked in by g7moreau, 6 years ago
  • Add acronym in zip folder root name
  • Property svn:executable set to *
File size: 11.8 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 libarchive-zip-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
170   push @{$data_set}, 'AUTHORS.txt', 'COPYRIGHT.txt', 'LICENCE.txt';
171   {
172      # Remove doublon
173      my %seen = ();
174      @{$data_set} = grep { ! $seen{$_}++ } @{$data_set};
175      }
176
177   # Create a Zip file
178   use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
179
180   my $zip = Archive::Zip->new();
181
182   for my $dataset (@{$data_set}) {
183      if (-d $dataset) {
184         # Folder case
185         $zip->addTree($dataset, "$acronym/$dataset");
186         }
187      elsif (-f $dataset) {
188         # File case
189         $zip->addFile(filename => $dataset, zipName => "$acronym/$dataset");
190         }
191      else {
192         # Strange case
193         print "Error: entry $dataset doesn't exists\n";
194         }
195      }
196
197   my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime time;
198   $year += 1900;
199   $mon++;
200   my $date = sprintf '%04i%02i%02i-%02i%02i', $year, $mon, $mday, $hour, $min;
201
202   # Save the Zip file
203   unless ($zip->writeToFileNamed("$current_dir/$acronym--$date.zip") == AZ_OK) {
204      die 'Error: zip write error';
205      }
206   }
207
208################################################################
209
210sub cmd_make_author {
211   my $meta = YAML::Syck::LoadFile("PROJECT-META.yml");
212
213   my $current_dir = Cwd::getcwd();
214
215   my $acronym    = $meta->{'project'}{'acronym'};
216   my $authors_list = $meta->{'project'}{'authors'};
217
218   if (-f "$current_dir/AUTHORS.txt") {
219      # Test for manual or automatically generated file
220      # Automatically generated file by project-meta
221      my $automatic;
222      open my $fh, '<', "$current_dir/AUTHORS.txt" or die $!;
223      for my $line (<$fh>) {
224         $line =~ m/Automatically generated .* project-meta/i and $automatic++;
225         }
226      close $fh;
227
228      if (not $automatic) {
229         print "Warning: AUTHORS.txt already exists\n";
230         return;
231         }
232
233      print "Warning: update AUTHORS.txt\n";
234      }
235
236   my $tt = Template->new(INCLUDE_PATH => '/usr/share/project-meta/template.d');
237   my $msg_format = '';
238   $tt->process('AUTHORS.tt',
239      {
240         acronym    => $acronym,
241         authorlist => $authors_list,
242      }, \$msg_format) || die $tt->error;
243
244   open my $fh,  '>', "$current_dir/AUTHORS.txt" or die $!;
245   print $fh "$msg_format\n\n";
246   close $fh;
247   }
248
249################################################################
250
251sub cmd_make_licence {
252   my $meta = YAML::Syck::LoadFile("PROJECT-META.yml");
253
254   my $current_dir = Cwd::getcwd();
255
256   if (-f "$current_dir/LICENCE.txt") {
257      print "Warning: LICENCE.txt already exists\n";
258      return;
259      }
260
261   my $licence = $meta->{'public-dap'}{'data-licence'};
262
263   if (not -f "/usr/share/project-meta/licence.d/$licence.txt") {
264      print "Error: licence $licence doesn't exists in project-meta database\n";
265      exit 1;
266      }
267
268   copy("/usr/share/project-meta/licence.d/$licence.txt", "$current_dir/LICENCE.txt")
269      or die "Error: licence copy failed - $!";
270
271   print "Info: LICENCE.txt file create\n";
272   return;
273   }
274
275################################################################
276
277sub cmd_make_copyright {
278   my $meta = YAML::Syck::LoadFile("PROJECT-META.yml");
279
280   my $current_dir = Cwd::getcwd();
281
282   if (-f "$current_dir/COPYRIGHT.txt") {
283      # Test for manual or automatically generated file
284      # Automatically generated file by project-meta
285      my $automatic;
286      open my $fh, '<', "$current_dir/COPYRIGHT.txt" or die $!;
287      for my $line (<$fh>) {
288         $line =~ m/Automatically generated .* project-meta/i and $automatic++;
289         }
290      close $fh;
291
292      if (not $automatic) {
293         print "Warning: COPYRIGHT.txt already exists\n";
294         return;
295         }
296
297      print "Warning: update COPYRIGHT.txt\n";
298      }
299   
300   my $tt = Template->new(
301      INCLUDE_PATH   => '/usr/share/project-meta/template.d',
302      POST_CHOMP     => 1, # Remove space and carriage return after %]
303      );
304   my $msg_format = '';
305   $tt->process('COPYRIGHT.tt',
306      {
307         title       => $meta->{'project'}{'title'},
308         acronym     => $meta->{'project'}{'acronym'},
309         authorlist  => $meta->{'project'}{'authors'},
310         description => $meta->{'project'}{'short-description'},
311         licence     => $meta->{'public-dap'}{'data-licence'},
312         doi         => $meta->{'publication'}{'doi'},
313      }, \$msg_format) || die $tt->error;
314
315   open my $fh,  '>', "$current_dir/COPYRIGHT.txt" or die $!;
316   print $fh "$msg_format\n\n";
317   close $fh;
318   }
319
320################################################################
321
322sub cmd_list_licence {
323   opendir my $dh, '/usr/share/project-meta/licence.d/' or die $!;
324   for my $licence (readdir $dh) {
325      # Keep only file
326      next if not -f "/usr/share/project-meta/licence.d/$licence";
327     
328      # Keep only .txt file
329      next if not $licence =~ m/\.txt$/;
330
331      $licence =~ s/\.txt$//;
332      print "$licence\n";
333      }
334   closedir $dh;
335   }
336
337################################################################
338# documentation
339################################################################
340
341__END__
342
343=head1 NAME
344
345project-meta - opendata project metafile manager
346
347
348=head1 USAGE
349
350 project-meta help
351 project-meta version
352 project-meta check
353 project-meta make-link
354 project-meta make-author
355 project-meta make-licence
356 project-meta make-copyright
357 project-meta make-licence
358 project-meta list-licence
359
360=head1 DESCRIPTION
361
362project-meta is a small tool to maintain a set of open data files.
363
364=head1 COMMANDS
365
366Some command are defined in the source code but are not documented here.
367Theses could be not well defined, not finished, not well tested...
368You can read the source code and use them at your own risk
369(like for all the Klask code).
370
371=head2 check
372
373 project-meta check
374
375Check your F<PROJECT-META.yml> has the good key.
376If your metafile is not a valid YAML file,
377you can use C<yamllint> command to check just it's format.
378
379=head2 make-licence
380
381 project-meta make-licence
382
383Copy the licence file from the project-meta licence database at the current folder with the file name: LICENCE.txt.
384
385The licence is defined in the PROJECT-META.yml specification under the key C<public-dap/data-licence>.
386The list of possible licence is given with the command L<list-licence>.
387
388=head2 list-licence
389
390 project-meta list-licence
391
392Give the list of all the open data licence supported by the project-meta licence database.
393At this time the possible licence are:
394
395 license-ouverte-v2.0
396 open-database-license-v1.0
397
398
399=head1 METAFILE SPECIFICATION
400
401Each project must have an open data metafile which describe the project : C<PROJECT-META.yml>.
402The file is in YAML format because this is a human readable style of text file.
403
404You can find in the project-meta software a C<PROJECT-META.sample.yml> example.
405This one is actually the master reference specification!
406
407
408=head1 BUG
409
410 - make-link: folder/folder
411 - make-link: support multiple doi
412 - metafile: remove prop publication/url
413
414=head1 SEE ALSO
415
416yamllint
417
418
419=head1 AUTHOR
420
421Written by Gabriel Moreau, LEGI UMR5519, CNRS, Grenoble - France
422
423=head1 SPECIAL THANKS
424
425The list of people below did not directly contribute to project-meta's source code
426but provided me with some data, returned bugs
427or helped me in another small task like having new ideas ...
428Maybe I forgot your contribution in recent years,
429please forgive me in advance and send me an e-mail to correct this.
430
431Joel Sommeria, Julien Chauchat, Cyrille Bonamy, Antoine Mathieu.
432
433
434=head1 LICENSE AND COPYRIGHT
435
436Licence GNU GPL version 2 or later and Perl equivalent
437
438Copyright (C) 2017-2018 Gabriel Moreau <Gabriel.Moreau(A)univ-grenoble-alpes.fr>.
Note: See TracBrowser for help on using the repository browser.