Description: refactor copher for Sourceforge's changed interface
This is a pre-0.2.1 patch from upstream
Origin: http://copher.cvs.sourceforge.net/viewvc/copher/copher/copher.pl?r1=1.21&r2=1.19
Bug: http://sourceforge.net/tracker/?func=detail&aid=2874738&group_id=137217&atid=738087
Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=587061
Last-Update: 2010-06-25
--- copher-0.2.0.orig/copher.pl
+++ copher-0.2.0/copher.pl
@@ -19,6 +19,7 @@
use WWW::Mechanize;
use Carp;
use File::Basename;
+use Cwd 'abs_path';
###########
# 'Constants'
@@ -40,13 +41,17 @@
login_form_action => '/account/login.php',
projects => '/projects/',
home => '',
+ # These seem to no longer exist as of 20091013.
base_newpackage => '/project/admin/editpackages.php',
base_editpackages => '/project/admin/editpackages.php',
base_newrelease => '/project/admin/newrelease.php',
base_editreleases => '/project/admin/editreleases.php',
base_editrelease => '/project/admin/editreleases.php', # edit a single release
- base_deleterelease => undef # does not exist in sourceforge
- },
+ #
+ base_deleterelease => undef, # does not exist in sourceforge
+ base_filemanager => '/project/admin/explorer.php', # add e.g. ?group_id=137217
+ base_explorerajax => '/project/admin/explorer_ajax.php',
+},
rubyforge => {
login => '/account/login.php',
login_form_action => '/account/login.php',
@@ -67,7 +72,8 @@
my @sf_ftp_path = qw(incoming); # path to enter before uploading file
my $sf_frs = "frs.sourceforge.net";
-my $sf_frs_path = "uploads";
+my $sf_frs_path = "uploads"; # obsolete circa 20091013
+my $sf_frs_path_fmt = "/home/frs/project/%s/%s/%s/";
###########
# To be set by the script when they're determined:
@@ -447,6 +453,7 @@
print STDERR "Uploading files...\n";
&upload_files(\%release_files);
}
+exit; ##HERE
#print "Sleeping for 10 seconds to allow sourceforge to notice files...\n";
#sleep 10;
@@ -508,97 +515,6 @@
}
}
-if (! $package_id) {
- print STDERR "No package_id specified, fetching Edit Packages ('File Releases') page with group_id=$group_id... ";
- my $response = &editpackages_php($mech, $group_id);
- &save_page(sprintf("%02d-editpackages.html", $debug_pagenum++)) if $debug;
- print STDERR &check_response($mech, $response, 1) . "\n";
-
- my @packages = &get_packages($mech);
- foreach my $pkg (@packages) {
- print STDERR "Package: name: " . $pkg->{package_name} .', package_id: '. $pkg->{package_id} .', group_id: '. $pkg->{group_id} ."\n";
- if ($pkg->{package_name} eq $package_name) { # good!
- $package_id = $pkg->{package_id};
- # ensure $pkg->{group_id} eq $group_id? it "should"
- unless ($pkg->{group_id} eq $group_id) {
- warn $pkg->{group_id} . " doesn't match known group ID " . $group_id . "\n";
- }
- }
- }
- if (!$package_id) {
- print STDERR "Couldn't find a package with package_name $package_name\n";
- # future versions will be able to handle creation of new packages [todo]
-
- #print STDERR "Creating a new package...\n";
- exit 1; # not yet
- }
-}
-
-if (! $release_id) {
- print STDERR "No release_id specified, fetching Edit Releases page with group_id=$group_id, package_id=$package_id... ";
- # or "Fetching list of file releases for $package_name (group_id=$group_id, package_id=$package_id)... ";
- my $response = &editreleases_php($mech, $group_id, $package_id);
- &save_page(sprintf("%02d-editreleases.html", $debug_pagenum++)) if $debug;
- print STDERR &check_response($mech, $response, 1) . "\n";
-
- my @releases = &get_releases($mech);
- foreach my $rls (@releases) {
- debug("Release: name: " . $rls->{release_name} .', release_id: '. $rls->{release_id} .', package_id: '. $rls->{package_id} ."\n");
- if ($rls->{release_name} eq $release_name) {
- $release_id = $rls->{release_id};
- print STDERR "Found release with name $release_name, release_id is $release_id. Using...\n";
- # sanity-check group_id and package_id
- if ($group_id != $rls->{group_id} or $package_id != $rls->{package_id}) {
- warn "group_id or package_id mismatch! $rls->{group_id} != $group_id or $rls->{package_id} != $package_id. Probably will fail."
- }
- #last;
- }
- }
-
- if (!$release_id) {
- if ($opt{exists}) {
- print STDERR "Couldn't find a release with release_name $release_name, exiting (omit -E option to create new release)...\n";
- &close_copher(1);
- } else {
- print STDERR "Couldn't find a release with release_name $release_name, will create one...\n";
- }
- }
-}
-
-if (! $release_id) {
- print STDERR "No release_id specified, fetching New Release page... ";
- my $response = &newrelease_php($mech, $group_id, $package_id);
- &save_page(sprintf("%02d-newrelease.html", $debug_pagenum++)) if $debug;
- print STDERR &check_response($mech, $response, 1) . "\n";
-
- print STDERR "Adding new release (submitting form on New Release page)... ";
- my $response = &add_release($mech, $group_id, $package_id, $release_name);
- $new_release = 1;
- &save_page(sprintf("%02d-added_release.html", $debug_pagenum++)) if $debug;
- print STDERR &check_response($mech, $response, 1) . "\n";
-
- if ($site eq 'rubyforge') {
- # rubyforge doesn't automatically load the editrelease page next
- if ($mech->content =~ m|<a href="$urls{$site}->{base_editrelease}.*?release_id=(\d+)|) {
- $release_id = $1;
- print STDERR "Fetching Edit Release page, editing release $release_id... ";
- my $response = &editrelease_php($mech, $group_id, $package_id, $release_id);
- &save_page(sprintf("%02d-editrelease.html", $debug_pagenum++)) if $debug;
- print STDERR &check_response($mech, $response, 1) . "\n";
- } else {
- warn "unable to find release_id in output of add_release() -- see out.html\n";
- &close_copher;
- }
- }
-} else {
- print STDERR "Fetching Edit Release page, editing release $release_id... ";
- my $response = &editrelease_php($mech, $group_id, $package_id, $release_id);
- &save_page(sprintf("%02d-editrelease.html", $debug_pagenum++)) if $debug;
- print STDERR &check_response($mech, $response, 1) . "\n";
-}
-
-
-# Now add files to the release
my %release = (
id => $release_id,
date => $release_date || $current_date,
@@ -609,68 +525,169 @@
files => \%release_files
);
-if ($site eq 'rubyforge' && $new_release) {
- print STDERR "Skipping Step 1 -- already done.\n";
+if ($site eq 'sourceforge') {
+# notes_file => $notes_file,
+# changelog_file => $changelog_file,
+# files => \%release_files
+
+
} else {
- print STDERR "Carrying out Step 1: Edit Existing Release... ";
- my $response = &edit_release_step1($mech, $group_id, $package_id, \%release);
- &save_page(sprintf("%02d-step1-edit_existing_release.html", $debug_pagenum++)) if $debug;
- print STDERR &check_response($mech, $response, 0) . "\n";
-}
+ if (! $package_id) {
+ print STDERR "No package_id specified, fetching Edit Packages ('File Releases') page with group_id=$group_id... ";
+ my $response = &editpackages_php($mech, $group_id);
+ &save_page(sprintf("%02d-editpackages.html", $debug_pagenum++)) if $debug;
+ print STDERR &check_response($mech, $response, 1) . "\n";
+
+ my @packages = &get_packages($mech);
+ foreach my $pkg (@packages) {
+ print STDERR "Package: name: " . $pkg->{package_name} .', package_id: '. $pkg->{package_id} .', group_id: '. $pkg->{group_id} ."\n";
+ if ($pkg->{package_name} eq $package_name) { # good!
+ $package_id = $pkg->{package_id};
+ # ensure $pkg->{group_id} eq $group_id? it "should"
+ unless ($pkg->{group_id} eq $group_id) {
+ warn $pkg->{group_id} . " doesn't match known group ID " . $group_id . "\n";
+ }
+ }
+ }
+ if (!$package_id) {
+ print STDERR "Couldn't find a package with package_name $package_name\n";
+ # future versions will be able to handle creation of new packages [todo]
+
+ #print STDERR "Creating a new package...\n";
+ exit 1; # not yet
+ }
+ }
-if (%release_files) {
- if ($site eq 'rubyforge' && $new_release && @release_files == 1) {
- # only file already added in add_release()
- print STDERR "Skipping Step 2 (Add Files To This Releases) -- already done.";
- } elsif ($site eq 'rubyforge' && $opt{noupload}) {
- # since uploading is done in step2 in rubyforge, skip step2 if noupload is set
- } else {
- my $added_all = 0;
- while ($site ne 'rubyforge' || !$added_all) { # run edit_release_step2 once per file for rubyforge
- $added_all = 1;
- for my $f (keys %release_files) {
- unless ($release_files{$f}->{added}) {
- $added_all = 0; # (at least) one file left to add
- last;
+ if (! $release_id) {
+ print STDERR "No release_id specified, fetching Edit Releases page with group_id=$group_id, package_id=$package_id... ";
+ # or "Fetching list of file releases for $package_name (group_id=$group_id, package_id=$package_id)... ";
+ my $response = &editreleases_php($mech, $group_id, $package_id);
+ &save_page(sprintf("%02d-editreleases.html", $debug_pagenum++)) if $debug;
+ print STDERR &check_response($mech, $response, 1) . "\n";
+
+ my @releases = &get_releases($mech);
+ foreach my $rls (@releases) {
+ debug("Release: name: " . $rls->{release_name} .', release_id: '. $rls->{release_id} .', package_id: '. $rls->{package_id} ."\n");
+ if ($rls->{release_name} eq $release_name) {
+ $release_id = $rls->{release_id};
+ print STDERR "Found release with name $release_name, release_id is $release_id. Using...\n";
+ # sanity-check group_id and package_id
+ if ($group_id != $rls->{group_id} or $package_id != $rls->{package_id}) {
+ warn "group_id or package_id mismatch! $rls->{group_id} != $group_id or $rls->{package_id} != $package_id. Probably will fail."
}
+ #last;
+ }
+ }
+
+ if (!$release_id) {
+ if ($opt{exists}) {
+ print STDERR "Couldn't find a release with release_name $release_name, exiting (omit -E option to create new release)...\n";
+ &close_copher(1);
+ } else {
+ print STDERR "Couldn't find a release with release_name $release_name, will create one...\n";
}
- last if $added_all;
+ }
+ }
- print STDERR "Carrying out Step 2: Add Files To This Releases... \n";
- my $response = &edit_release_step2($mech, $group_id, $package_id, \%release);
- &save_page(sprintf("%02d-step2-add_files.html", $debug_pagenum++)) if $debug;
- print STDERR &check_response($mech, $response, 0) . "\n";
- if ($mech->content =~ /Error.*That filename already exists in this project space/) {
- # TODO: optionally delete and re-add the file? the user might have updated it...
- # should actually check BEFORE trying to add the file, though...
- print STDERR "Error: File already added...\n";
+ if (! $release_id) {
+ print STDERR "No release_id specified, fetching New Release page... ";
+ my $response = &newrelease_php($mech, $group_id, $package_id);
+ &save_page(sprintf("%02d-newrelease.html", $debug_pagenum++)) if $debug;
+ print STDERR &check_response($mech, $response, 1) . "\n";
+
+ print STDERR "Adding new release (submitting form on New Release page)... ";
+ my $response = &add_release($mech, $group_id, $package_id, $release_name);
+ $new_release = 1;
+ &save_page(sprintf("%02d-added_release.html", $debug_pagenum++)) if $debug;
+ print STDERR &check_response($mech, $response, 1) . "\n";
+
+ if ($site eq 'rubyforge') {
+ # rubyforge doesn't automatically load the editrelease page next
+ if ($mech->content =~ m|<a href="$urls{$site}->{base_editrelease}.*?release_id=(\d+)|) {
+ $release_id = $1;
print STDERR "Fetching Edit Release page, editing release $release_id... ";
my $response = &editrelease_php($mech, $group_id, $package_id, $release_id);
&save_page(sprintf("%02d-editrelease.html", $debug_pagenum++)) if $debug;
print STDERR &check_response($mech, $response, 1) . "\n";
+ } else {
+ warn "unable to find release_id in output of add_release() -- see out.html\n";
+ &close_copher;
}
}
+ } else {
+ print STDERR "Fetching Edit Release page, editing release $release_id... ";
+ my $response = &editrelease_php($mech, $group_id, $package_id, $release_id);
+ &save_page(sprintf("%02d-editrelease.html", $debug_pagenum++)) if $debug;
+ print STDERR &check_response($mech, $response, 1) . "\n";
}
-}
-if ($site eq 'rubyforge' && $new_release && @release_files == 1) {
- # only file already added in add_release()
- print STDERR "Skipping Step 3 (Edit Files To This Releases) -- already done.";
-} else {
- print STDERR "Carrying out Step 3: Edit Files In This Release...\n";
- my $value = &edit_release_step3($mech, $group_id, $package_id, \%release);
- &save_page(sprintf("%02d-step3-edit_files.html", $debug_pagenum++)) if $debug;
- if (!$value) {
- print STDERR "Error doing step 3. $value\n";
+
+# Now add files to the release
+
+ if ($site eq 'rubyforge' && $new_release) {
+ print STDERR "Skipping Step 1 -- already done.\n";
+ } else {
+ print STDERR "Carrying out Step 1: Edit Existing Release... ";
+ my $response = &edit_release_step1($mech, $group_id, $package_id, \%release);
+ &save_page(sprintf("%02d-step1-edit_existing_release.html", $debug_pagenum++)) if $debug;
+ print STDERR &check_response($mech, $response, 0) . "\n";
}
-}
-if ($opt{notice} && $site eq 'sourceforge') { # rubyforge does not have this option
- # Step 4. Email Release Notice
- print STDERR "Carrying out Step 4: Email Release Notice...\n";
- my $response = &edit_release_step4($mech, $group_id, $package_id, \%release);
- &save_page(sprintf("%02d-step4-email_release_notice.html", $debug_pagenum++)) if $debug;
- print STDERR &check_response($mech, $response, 0) . "\n";
+ if (%release_files) {
+ if ($site eq 'rubyforge' && $new_release && @release_files == 1) {
+ # only file already added in add_release()
+ print STDERR "Skipping Step 2 (Add Files To This Releases) -- already done.";
+ } elsif ($site eq 'rubyforge' && $opt{noupload}) {
+ # since uploading is done in step2 in rubyforge, skip step2 if noupload is set
+ } else {
+ my $added_all = 0;
+ while ($site ne 'rubyforge' || !$added_all) { # run edit_release_step2 once per file for rubyforge
+ $added_all = 1;
+ for my $f (keys %release_files) {
+ unless ($release_files{$f}->{added}) {
+ $added_all = 0; # (at least) one file left to add
+ last;
+ }
+ }
+ last if $added_all;
+
+ print STDERR "Carrying out Step 2: Add Files To This Releases... \n";
+ my $response = &edit_release_step2($mech, $group_id, $package_id, \%release);
+ &save_page(sprintf("%02d-step2-add_files.html", $debug_pagenum++)) if $debug;
+ print STDERR &check_response($mech, $response, 0) . "\n";
+ if ($mech->content =~ /Error.*That filename already exists in this project space/) {
+ # TODO: optionally delete and re-add the file? the user might have updated it...
+ # should actually check BEFORE trying to add the file, though...
+ print STDERR "Error: File already added...\n";
+ print STDERR "Fetching Edit Release page, editing release $release_id... ";
+ my $response = &editrelease_php($mech, $group_id, $package_id, $release_id);
+ &save_page(sprintf("%02d-editrelease.html", $debug_pagenum++)) if $debug;
+ print STDERR &check_response($mech, $response, 1) . "\n";
+ }
+ }
+ }
+ }
+
+ if ($site eq 'rubyforge' && $new_release && @release_files == 1) {
+ # only file already added in add_release()
+ print STDERR "Skipping Step 3 (Edit Files To This Releases) -- already done.";
+ } else {
+ print STDERR "Carrying out Step 3: Edit Files In This Release...\n";
+ my $value = &edit_release_step3($mech, $group_id, $package_id, \%release);
+ &save_page(sprintf("%02d-step3-edit_files.html", $debug_pagenum++)) if $debug;
+ if (!$value) {
+ print STDERR "Error doing step 3. $value\n";
+ }
+ }
+
+ if ($opt{notice} && $site eq 'sourceforge') { # rubyforge does not have this option
+ # (apparently sourceforge doesn't either, any more -20091013)
+ # Step 4. Email Release Notice
+ print STDERR "Carrying out Step 4: Email Release Notice...\n";
+ my $response = &edit_release_step4($mech, $group_id, $package_id, \%release);
+ &save_page(sprintf("%02d-step4-email_release_notice.html", $debug_pagenum++)) if $debug;
+ print STDERR &check_response($mech, $response, 0) . "\n";
+ }
}
print STDERR "Finished!\n";
@@ -760,7 +777,43 @@
# Warning: any/some of these may be empty
return $mech->get($base_url."?group_id=$group_id&package_id=$package_id");
- }
+}
+
+# TODO:
+# for release notes file, call explorerajax_php
+# with release_noteable => 1
+# for each (other) file, call explorerajax_php
+# with release_notable => 0,
+# release_notes => $release_notes_filename (path from FRS root, e.g. /$package_name/$release_name/notes)
+sub explorerajax_php($$$$@) {
+ my ($mech, $group_id, $package_id, $filename);
+ ($mech, $group_id, $package_id, $filename, %_) = @_;
+
+ my $base_url = $sites{$site}.$urls{$site}->{base_explorerajax};
+ my $url = $base_url."?group_id=$group_id";
+
+ my %defaults = (
+ operation => 'save_settings',
+ save_settings => 'Save',
+ original_filename => $filename,
+ filename => $filename,
+ filepath => "/$package_name/$release_name/$filename",
+ );
+ for (keys %defaults) {
+ $_{$_} = $defaults{$_} unless defined $_{$_};
+ }
+
+ for (keys %_) {
+ $url .= "&$_=$_{$_}";
+ }
+
+ # Example URL:
+ # https://sourceforge.net/project/admin/explorer_ajax.php?group_id=137217&default_download=&filepath=%2Fcopher%2Fcopher-0.2.1%2Fcopher-0.2.1.tar.gz&operation=save_settings&original_filename=copher-0.2.1.tar.gz&filename=copher-0.2.1.tar.gz&download_label=&release_notable=1&default_linux=linux&default_mac=mac&default_windows=windows&default_bsd=bsd&default_solaris=solaris&default_others=others&release_notes=&save_settings=Save
+
+ # returned content should be: { "val": 100, "message": "OK" }
+ return $mech->get($url);
+}
+
# Get a list of packages from editpackages.php page (which must already be loaded in $mech)
sub get_packages ($) {
@@ -900,19 +953,42 @@
my $release_files = shift;
my @fullpaths = map { $release_files->{$_}->{'fullpath'} } keys %$release_files;
- my $obj = File::Rsync->new( { archive => 1, rsh => 'ssh' } );
+ my $obj = File::Rsync->new( { times => 1, rsh => 'ssh', relative => 1, 'omit-dir-times' => 1} );
+
+ require File::Temp;
+ my $tmpdir = File::Temp::tempdir();#CLEANUP => 1) or die "Failed to create temporary directory: $!\n";
+ print STDERR "\$tmpdir=$tmpdir\n";
+ symlink('.', "$tmpdir/$package_name") or die "Failed to create package symlink in $tmpdir: $!\n";
+
+ my $srcpath = "$tmpdir/./$package_name/$release_name";
+ my $dstpath = sprintf($sf_frs_path_fmt,
+ substr($project_name, 0, 1),
+ substr($project_name, 0, 2),
+ $project_name
+ );
+ print "src path is $srcpath\n";
+ print "dst path is $dstpath\n";
+
+ # e.g. final destination path: /home/frs/project/c/co/copher/copher/copher-0.0.0/
foreach my $file (@fullpaths) {
print STDERR "Uploading $file... ";
- if ($obj->exec( { src => $file, dest => "$user{loginname}\@$sf_frs:$sf_frs_path" } )) {
+ my $dirname = abs_path(dirname($file));
+ my $basename = basename $file;
+ unlink("$tmpdir/$release_name") if -l "$tmpdir/$release_name";
+ symlink("$dirname", "$tmpdir/$release_name") or die "Failed to create release symlink in $tmpdir: $!\n";
+
+ my $cmd = $obj->getcmd( { src => "$srcpath/$basename", dest => "$user{loginname},$project_name\@$sf_frs:$dstpath" });
+ #print STDERR "\n rsync command: @$cmd\n";
+
+ if ($obj->exec( { src => "$srcpath/$basename", dest => "$user{loginname},$project_name\@$sf_frs:$dstpath" } )) {
print STDERR "Done\n";
} else {
print STDERR "Failed: $!.\n";
}
-
$release_files->{basename($file)}->{'uploaded'} = 1; # keep track of which files we've uploaded
}
- }
+}
sub upload_files_scp ($) {
# sourceforge says scp is not supported; it doesn't work
@@ -983,7 +1059,7 @@
# https://frs.sourceforge.net/U/US/USERNAME/uploads
# HTTP::Webdav
print STDERR "ERROR: webdav uploader not yet implemented\n";
- }
+}
# Add a new release by submitting the form on the newrelease.php page
# Pre-condition: $mech->content is the newrelease.php page with correct package_id and group_id