Skip to content

Instantly share code, notes, and snippets.

@jay
Last active December 15, 2022 04:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jay/dcb5ca6813f7efb01382a4fb089e20fe to your computer and use it in GitHub Desktop.
Save jay/dcb5ca6813f7efb01382a4fb089e20fe to your computer and use it in GitHub Desktop.
fetch and checkout a curl release from the canonical repo
#!/usr/bin/env perl
=begin comment
README
./checkout-curl-release.pl <"latest" | tag | version>
This script fetches and checks out the release tag marked as "latest" (or
a user-specified release tag or version) from the canonical curl repo on
github, and then modifies the curl/libcurl version includes to use the version
information from that release tag instead of DEV.
Written in response to https://github.com/curl/curl/issues/1076
Requires curl, git and jq (https://stedolan.github.io/jq/download/)
Copyright (C) 2016 Jay Satiro <raysatiro@yahoo.com>
http://curl.haxx.se/docs/copyright.html
https://gist.github.com/jay/dcb5ca6813f7efb01382a4fb089e20fe
=end comment
=cut
use strict;
use warnings;
my $HEADER = "include/curl/curlver.h";
my $CHEADER = "src/tool_version.h";
if(!defined $ARGV[0]) {
die "Usage: ./checkout-curl-release.pl <\"latest\" | tag | version>\n";
}
-e ".git" || die ".git not found";
-e "$HEADER" || die "$HEADER not found";
-e "$CHEADER" || die "$CHEADER not found";
`git --version` || die "git not found";
`curl --version` || die "curl not found";
`jq --version` || die "jq not found";
my $github_repo_name = "curl/curl";
my $tag;
my $user_specified;
my %ver;
# Determine the tag and version
if(lc $ARGV[0] eq lc "latest") {
my $url = "https://api.github.com/repos/$github_repo_name/releases/latest";
$tag = 'curl --fail --location -sS --proto =https "' . $url . '" | ' .
'jq --join-output ".tag_name | select(type == \\"string\\")"';
$tag = `$tag`;
!$? || die; # this only covers jq failure, there's no pipefail in cmd shell.
$tag =~ s/\r?\n$//;
$tag =~ /^curl-(\d+)_(\d+)_(\d+)$/ or die "Failed parsing tag";
($ver{major}, $ver{minor}, $ver{patch}) = ($1, $2, $3);
print "The curl release tag marked latest on GitHub is $tag.\n";
}
else {
$user_specified = 1;
$tag = $ARGV[0];
$tag =~ /^(?:curl-)?(\d+)[._](\d+)[._](\d+)$/ or die "Failed parsing tag";
$tag = "curl-$1_$2_$3";
($ver{major}, $ver{minor}, $ver{patch}) = ($1, $2, $3);
print "The user-specified curl release tag is $tag.\n";
}
$ver{full} = "$ver{major}.$ver{minor}.$ver{patch}",
$ver{num} = sprintf("%02X%02X%02X", $ver{major}, $ver{minor}, $ver{patch});
# Check that the tag exists in the repo
`git merge-base --is-ancestor $tag $tag 2>&1`;
if($?) {
print "Tag not found in local repo. Fetching all tags.\n";
# Fetch can hang waiting for auth if the specified repo isn't public
`git fetch -q --tags https://github.com/$github_repo_name.git`;
!$? || die "Failed updating curl repo tags";
`git merge-base --is-ancestor $tag $tag 2>&1`;
!$? || die "Tag not found: $tag";
}
# Reset the curl version headers
`git checkout HEAD "$HEADER"`;
!$? || die "Failed resetting \"$HEADER\"";
`git checkout HEAD "$CHEADER"`;
!$? || die "Failed resetting \"$CHEADER\"";
# Checkout the tag
`git -c advice.detachedHead=false checkout -q $tag`;
!$? || die "Failed checking out tag $tag";
# Get the tag's commit date
$ver{timestamp} = `git log --date=short "--pretty=format:%cd" -n 1`;
!$? || die "Failed retrieving commit date";
print "Commit date: $ver{timestamp}\n";
# Modify HEADER include to show tag version
my $fh;
my $content;
print "Modifying \"$HEADER\".\n";
open($fh, "<:crlf", $HEADER) || die "Failed reading \"$HEADER\" : $!";
{
local $/;
$content = <$fh>;
}
close($fh);
$content =~ s/^(#define LIBCURL_VERSION) .*/$1 \"$ver{full}\"/gm or die;
$content =~ s/^(#define LIBCURL_VERSION_NUM) .*/$1 0x$ver{num}/gm or die;
$content =~ s/^(#define LIBCURL_VERSION_MAJOR) .*/$1 $ver{major}/gm or die;
$content =~ s/^(#define LIBCURL_VERSION_MINOR) .*/$1 $ver{minor}/gm or die;
$content =~ s/^(#define LIBCURL_VERSION_PATCH) .*/$1 $ver{patch}/gm or die;
$content =~ s/^(#define LIBCURL_TIMESTAMP) .*/$1 \"$ver{timestamp}\"/gm or die;
open($fh, ">", $HEADER) || die "Failed writing \"$HEADER\" : $!";
print $fh $content;
close($fh);
# Modify CHEADER include to show tag version
print "Modifying \"$CHEADER\".\n";
open($fh, "<:crlf", $CHEADER) || die "Failed reading \"$CHEADER\" : $!";
{
local $/;
$content = <$fh>;
}
close($fh);
$content =~ s/^(#define CURL_VERSION) .*/$1 \"$ver{full}\"/gm or die;
$content =~ s/^(#define CURL_VERSION_MAJOR) .*/$1 $ver{major}/gm or die;
$content =~ s/^(#define CURL_VERSION_MINOR) .*/$1 $ver{minor}/gm or die;
$content =~ s/^(#define CURL_VERSION_PATCH) .*/$1 $ver{patch}/gm or die;
open($fh, ">", $CHEADER) || die "Failed writing \"$CHEADER\" : $!";
print $fh $content;
close($fh);
# Done
print "Done: curl $ver{full} has been checked out and the includes have " .
"been updated.\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment