package Commods;
use IO::File;
+use IO::Pipe;
use HTTP::Request::Common ();
use POSIX;
+use LWP::UserAgent;
use strict;
use warnings;
&get_our_version &check_tsv_line
&pipethrough_prep &pipethrough_run
&pipethrough_run_along &pipethrough_run_finish
- &pipethrough_run_gzip
+ &pipethrough_run_gzip &http_useragent &version_core
+ &http_useragent_string_map
&cgipostform &yarrgpostform &cgi_get_caller
- &set_ctype_utf8 $masterinfoversion);
+ &set_ctype_utf8 $masterinfoversion
+ &source_tarball);
%EXPORT_TAGS = ( );
@EXPORT_OK = qw();
}
-our $masterinfoversion= 2; # version we understand
+our $masterinfoversion= 2; # version we understand.
+#
+# To extend the source-info.txt format:
+#
+# * Commods.pm:parse_info1
+# add code to parse new version
+#
+# * source-info.txt
+# add new information
+#
+# If new data should NOT be in master-info.txt too:
+#
+# * update-master-info:process_some_info
+# check that code for converting source-info to master-info
+# removes the extra info; add code to remove it if necessary
+#
+# * db-idempotent-populate
+# if database schema is extended, add code to copy data
+#
+# If new data DOES need to be in master-info.txt too:
+#
+# * Commods.pm:$masterinfoversion
+# increment
+#
+# * update-master-info:process_some_info
+# add code to convert new version to old, by removing
+# extra info conditionally depending on version
our %oceans; # eg $oceans{'Midnight'}{'Ruby'}{'Eta Island'}= $sources;
our %clients; # eg $clients{'ypp-sc-tools'}= [ qw(last-page) ];
# when extending the format of source-info in a non-backward
# compatible way, be sure to update update-master-info too.
-sub parse_info1 ($$) {
- my ($mmfn,$src)= @_;
- my $mm= new IO::File $mmfn, 'r' or die "$mmfn $!";
+sub parse_info1 ($$$) {
+ my ($mmfn,$src,$enoentok)= @_;
+ my $mm= new IO::File $mmfn, 'r';
+ if (!$mm) {
+ return if $enoentok && $!==&ENOENT;
+ die "$mmfn $!";
+ }
my @ctx= ();
while (<$mm>) {
next if m/^\s*\#/;
}
sub parse_info_clientside () {
- my $yarrg= $ENV{'YPPSC_YARRG_DICT_UPDATE'};
- return unless $yarrg;
- my $master= fetch_with_rsync("info-$masterinfoversion");
- parse_info1($master,'s');
- my $local= '_local-info.txt';
- if (stat $local) {
- parse_info1($local,'s');
- } else {
- die "$local $!" unless $! == &ENOENT;
- }
+ my $master= fetch_with_rsync("info-v$masterinfoversion");
+ parse_info1($master,'s',1);
+ parse_info1('_local-info.txt','s',1);
}
sub fetch_with_rsync ($) {
}
sub parse_info_serverside () {
- parse_info1('source-info.txt','s');
+ parse_info1('source-info.txt','s',0);
+ parse_info1('tree-info.txt','t',1);
}
sub parse_info_serverside_ocean ($) {
my ($oceanname) = @_;
die "unknown ocean $oceanname ?" unless exists $oceans{$oceanname};
- parse_info1("_ocean-".(lc $oceanname).".txt",'s');
+ parse_info1("_ocean-".(lc $oceanname).".txt", 's',0);
}
sub parse_pctb_commodmap () {
my ($aref,$prefix) = @_;
$aref->{"${prefix}name"}= 'ypp-sc-tools yarrg';
$aref->{"${prefix}fixes"}= 'lastpage checkpager';
-
- my $version= `git-describe --tags HEAD || echo 0unknown`; $? and die $?;
- chomp($version);
- $aref->{"${prefix}version"}= $version;
+ $aref->{"${prefix}version"}= version_core();
return $aref;
# clientname "ypp-sc-tools"
# clientversion 2.1-g2e06a26 [from git-describe --tags HEAD]
# clientfixes "lastpage" [space separated list]
}
+sub version_core () {
+ my $version= `
+ if type -p git-describe >/dev/null 2>&1; then
+ gd=git-describe
+ else
+ gd="git describe"
+ fi
+ \$gd --tags HEAD || echo 0unknown
+ `; $? and die $?;
+ chomp($version);
+ return $version;
+}
+
sub pipethrough_prep () {
my $tf= IO::File::new_tmpfile() or die $!;
return $tf;
setlocale(LC_CTYPE, "en.UTF-8");
}
+sub http_useragent_string_map ($$) {
+ my ($caller_lib_agent, $reason_style_or_caller) = @_;
+ $caller_lib_agent =~ y/A-Za-z/N-ZA-Mn-za-m/;
+ $caller_lib_agent =~ s/\s/_/g;
+ my $version= version_core();
+ return "yarrg/$version ($reason_style_or_caller)".
+ " $caller_lib_agent".
+ " (http://yarrg.chiark.net/intro)";
+}
+
+sub http_useragent ($) {
+ my ($who) = @_;
+ my $ua= LWP::UserAgent->new;
+ my $base= $ua->_agent();
+ $ua->agent(http_useragent_string_map($base, $who));
+ return $ua;
+}
+
+sub source_tarball ($$) {
+ my ($sourcebasedir,$spitoutfn) = @_;
+
+ my $pipe= new IO::Pipe or die $!;
+ my $pid= fork(); defined $pid or die $!;
+ if (!$pid) {
+ $ENV{'YPPSC_YARRG_SRCBASE'}= $sourcebasedir;
+ $pipe->writer();
+ exec '/bin/sh','-c','
+ cd -P "$YPPSC_YARRG_SRCBASE"
+ (
+ git-ls-files -z;
+ git-ls-files -z --others --exclude-from=.gitignore;
+ if test -d .git; then find .git -print0; fi
+ ) | (
+ cpio -Hustar -o --quiet -0 -R 1000:1000 || \
+ cpio -Hustar -o --quiet -0
+ ) | gzip
+ ';
+ die $!;
+ }
+ $pipe->reader();
+
+ my ($d, $l);
+ while ($l= read $pipe, $d, 65536) {
+ $spitoutfn->($d);
+ }
+ waitpid $pid,0;
+ defined $l or die "read pipe $!";
+ $pipe->error and die "pipe error $!";
+ close $pipe;
+ # deliberately ignore errors
+}
+
1;