Skip to content

Commit 1d65f7e

Browse files
author
Sergio Durigan Junior
committed
Improve wcurl version comparison mechanism
We've been having a some problems with version comparison in the script. The approach we've taken so far is to decompose the current curl version into two variables (major and minor), and then perform comparisons against these components separately. It works, but it's confusing. Another possible approach would be to use a C-style version normalization (basically a printf "%02d%02d%02d") and then perform comparisons against the versions we want. The problem is that these versions need also to be normalized, which can be confusing as well. I decided to implement the second approach but abstract it as a simple function that can take a regular version string like "8.16.0" as well as a comparison operator that will then be passed onto to "test". This reads much nicer and abstracts the complexities of version normalization away. Unfortunately due to the limitations of shell scripting it's not easy to deduplicate code in this scenario, but that should be OK for now. Signed-off-by: Sergio Durigan Junior <[email protected]>
1 parent 9a08506 commit 1d65f7e

File tree

2 files changed

+88
-22
lines changed

2 files changed

+88
-22
lines changed

tests/tests.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,35 @@ testCurlBinaryOption()
246246
assertContains "Verify whether 'wcurl' invokes the binary specified by '--curl-binary'" "${bin}" "${curlbin}"
247247
}
248248

249+
testCurlVersionComparison()
250+
{
251+
# Verify that using a very old curl version correctly omits
252+
# --parallel, --no-clobber and --parallel-max-host.
253+
url='example.com'
254+
curlbin="${ROOTDIR}/tests/curl-mock-version"
255+
ret=$(CURL_MOCK_VERSION="1.0.0" ${WCURL_CMD} --dry-run --curl-binary "${curlbin}" "${url}" "${url}")
256+
assertNotContains "Verify whether 'wcurl' correctly omits --parallel when using very old curl" "${ret}" '--parallel'
257+
assertNotContains "Verify whether 'wcurl' correctly omits --no-clobber when using very old curl" "${ret}" '--no-clobber'
258+
assertNotContains "Verify whether 'wcurl' correctly omits --parallel-max-host when using very old curl" "${ret}" '--parallel-max-host'
259+
260+
# Verify that using a curl version that's >= 7.66.0 and < 7.83.0
261+
# correctly adds --parallel but omits --no-clobber and --parallel-max-host.
262+
ret=$(CURL_MOCK_VERSION="7.66.0" ${WCURL_CMD} --dry-run --curl-binary "${curlbin}" "${url}" "${url}")
263+
assertContains "Verify whether 'wcurl' correctly adds --parallel when using curl >= 7.66.0" "${ret}" '--parallel'
264+
assertNotContains "Verify whether 'wcurl' correctly omits --no-clobber when using curl >= 7.66.0 && curl < 7.83.0" "${ret}" '--no-clobber'
265+
assertNotContains "Verify whether 'wcurl' correctly omits --parallel-max-host when using curl >= 7.66.0 && curl < 8.16.0" "${ret}" '--parallel-max-host'
266+
267+
# Verify that using a curl version that's >= 7.83.0 and < 8.16.0 correctly adds --no-clobber but omits --parallel-max-host.
268+
ret=$(CURL_MOCK_VERSION="7.83.0" ${WCURL_CMD} --dry-run --curl-binary "${curlbin}" "${url}" "${url}")
269+
assertContains "Verify whether 'wcurl' correctly adds --no-clobber when using curl >= 7.83.0" "${ret}" '--no-clobber'
270+
assertNotContains "Verify whether 'wcurl' correctly omits --parallel-max-host when using curl >= 7.83.0 && curl < 8.16.0" "${ret}" '--parallel-max-host'
271+
272+
# Verify that using a curl version that's >= 8.16.0 correctly adds
273+
# --parallel-max-host.
274+
ret=$(CURL_MOCK_VERSION="8.16.0" ${WCURL_CMD} --dry-run --curl-binary "${curlbin}" "${url}" "${url}")
275+
assertContains "Verify whether 'wcurl' correctly adds --parallel-max-host. when using curl >= 8.16.0" "${ret}" '--parallel-max-host'
276+
}
277+
249278
## Ideas for tests:
250279
##
251280
## - URL with whitespace

wcurl

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,49 @@ readonly UNSAFE_PERCENT_ENCODE="%2F %5C"
128128
# Whether to invoke curl or not.
129129
DRY_RUN="false"
130130

131+
# The current version of curl.
132+
CURL_VERSION=""
133+
# The normalized curl version, in the format "XXYYZZ", where "XX" is
134+
# the zero-padded major version, "YY" is the zero-padded minor
135+
# version and "ZZ" is the zero-padded patch version.
136+
CURL_NORMALIZED_VERSION=""
137+
131138
# Sanitize parameters.
132139
sanitize()
133140
{
134141
if [ -z "${URLS}" ]; then
135142
error "You must provide at least one URL to download."
136143
fi
137144

138-
readonly CURL_OPTIONS CURL_BINARY URLS DRY_RUN HAS_USER_SET_OUTPUT
145+
CURL_VERSION=$(${CURL_BINARY} --version | head -n1 | cut -f2 -d' ')
146+
if [ -z "${CURL_VERSION}" ]; then
147+
error "Unable to determine curl version. Is curl installed?"
148+
fi
149+
150+
CURL_NORMALIZED_VERSION=$(normalize_version "${CURL_VERSION}")
151+
152+
readonly CURL_OPTIONS \
153+
CURL_BINARY \
154+
URLS \
155+
DRY_RUN \
156+
HAS_USER_SET_OUTPUT \
157+
CURL_VERSION \
158+
CURL_NORMALIZED_VERSION
159+
}
160+
161+
# Print the normalized format of a version specified as the first argument.
162+
#
163+
# The normalized version has the format "XXYYZZ", where "XX" is the
164+
# zero-padded major version, "YY" is the zero-padded minor version and
165+
# "ZZ" is the zero-padded patch version.
166+
normalize_version()
167+
{
168+
version="${1}"
169+
vermaj=$(printf "%s" "${version}" | cut -f1 -d.)
170+
vermin=$(printf "%s" "${version}" | cut -f2 -d.)
171+
verpatch=$(printf "%s" "${version}" | cut -f3 -d.)
172+
173+
printf "%02d%02d%02d" "${vermaj}" "${vermin}" "${verpatch}"
139174
}
140175

141176
# Indicate via exit code whether the string given in the first parameter
@@ -203,36 +238,38 @@ get_url_filename()
203238
# No slash means there was just a hostname and no path; return empty string.
204239
}
205240

241+
# Given a version (in the format MAJOR.MINOR) as the first argument
242+
# and an operator as the second argument, perform a comparison against
243+
# the current curl version.
244+
compare_curl_version()
245+
{
246+
# Any of: -lt, -le, -eq, -gt, -ge
247+
operator="${1}"
248+
version="${2}"
249+
version_to_compare=$(normalize_version "${version}")
250+
251+
test "${CURL_NORMALIZED_VERSION}" "${operator}" "${version_to_compare}"
252+
}
253+
206254
# Execute curl with the list of URLs provided by the user.
207255
exec_curl()
208256
{
209257
CMD="${CURL_BINARY} "
210258

211-
# Store version to check if it supports --no-clobber, --parallel and --parallel-max-host.
212-
curl_version=$($CMD --version | cut -f2 -d' ' | head -n1)
213-
curl_version_major=$(echo "$curl_version" | cut -f1 -d.)
214-
curl_version_minor=$(echo "$curl_version" | cut -f2 -d.)
215-
216259
CURL_NO_CLOBBER=""
217260
CURL_PARALLEL=""
218261

219-
if [ "${curl_version_major}" -ge 8 ]; then
262+
# --parallel is only supported since 7.66.0.
263+
if compare_curl_version -ge "7.66.0"; then
264+
CURL_PARALLEL="--parallel"
265+
fi
266+
# --no-clobber is only supported since 7.83.0.
267+
if compare_curl_version -ge "7.83.0"; then
220268
CURL_NO_CLOBBER="--no-clobber"
221-
CURL_PARALLEL="--parallel --parallel-max-host 5"
222-
223-
# --parallel-max-host is only supported since 8.16.0.
224-
if [ "${curl_version_major}" -eq 8 ] && [ "${curl_version_minor}" -lt 16 ]; then
225-
CURL_PARALLEL="--parallel"
226-
fi
227-
elif [ "${curl_version_major}" -eq 7 ]; then
228-
# --no-clobber is only supported since 7.83.0.
229-
if [ "${curl_version_minor}" -ge 83 ]; then
230-
CURL_NO_CLOBBER="--no-clobber"
231-
fi
232-
# --parallel is only supported since 7.66.0.
233-
if [ "${curl_version_minor}" -ge 66 ]; then
234-
CURL_PARALLEL="--parallel"
235-
fi
269+
fi
270+
# --parallel-max-host is only supported since 8.16.0.
271+
if compare_curl_version -ge "8.16.0"; then
272+
CURL_PARALLEL="${CURL_PARALLEL} --parallel-max-host 5"
236273
fi
237274

238275
# Detecting whether we need --parallel. It is easier to rely on

0 commit comments

Comments
 (0)