Skip to content

Commit cf309ed

Browse files
author
José Valim
committed
Add docs to Mix.Version and make version always the first arg
1 parent da0a956 commit cf309ed

File tree

2 files changed

+109
-51
lines changed

2 files changed

+109
-51
lines changed

lib/mix/lib/mix/version.ex

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,72 @@
11
defmodule Mix.Version do
2+
@moduledoc %B"""
3+
This module provides functions for parsing and matching
4+
versions with requirements.
5+
6+
A version is a string or a `Mix.Version.Schema` generated
7+
after parsing via `Mix.Version.parse/1`. A requirement is
8+
a string that follows a specific format.
9+
10+
`Mix.Version` parsing and requirements follows
11+
[SemVer 2.0 schema](http://semver.org/) and you will get
12+
the most of Mix' version system by following it. In order
13+
to support integration with projects that may
14+
follow different versioning schemas, Elixir won't choke
15+
on unknown versions, however you won't be able to use
16+
Mix requirements with such unformatted versions.
17+
18+
## Versions
19+
20+
In a nutshell, a version is given by three numbers:
21+
22+
MAJOR.MINOR.PATCH
23+
24+
Pre-releases are supported by appending `-[0-9A-Za-z-\.]`:
25+
26+
"1.0.0-alpha3"
27+
28+
Build information can be added by appending `+[0-9A-Za-z-\.]`:
29+
30+
"1.0.0-alpha3+20130417140000"
31+
32+
## Requirements
33+
34+
Requirements allow you to specify which versions of a given
35+
dependency you are willing to work against. It supports common
36+
operators like `>=`, `<=`, `>`, `==` and friends that would
37+
work as one would expect:
38+
39+
# Only version 2.0.0
40+
"== 2.0.0"
41+
42+
# Anything later than 2.0.0
43+
"> 2.0.0"
44+
45+
Requirements also support `and` and `or` for complex conditions:
46+
47+
# 2.0.0 and later until 2.1.0
48+
">= 2.0.0 and < 2.1.0"
49+
50+
Since the example above is such a common requirement, it can
51+
be expressed as:
52+
53+
"~> 2.0.0"
54+
55+
"""
56+
57+
@type t :: String.t | Mix.Version.Schema.t
58+
@type requirement :: String.t | Mix.Version.Requirement.t
59+
260
@type matchable :: { major :: String.t | non_neg_integer,
361
minor :: non_neg_integer | nil,
462
patch :: non_neg_integer | nil,
563
pre :: { String.t, non_neg_integer } | nil }
664

65+
import Kernel, except: [match?: 2]
66+
67+
defrecord Schema, major: 0, minor: 0, patch: 0, build: nil, source: nil
68+
defrecord Requirement, source: nil, matchspec: nil
69+
770
defexception InvalidRequirement, reason: :invalid_requirement do
871
def message(InvalidRequirement[reason: reason]) when is_binary(reason) do
972
{ first, rest } = String.next_grapheme(reason)
@@ -15,29 +78,24 @@ defmodule Mix.Version do
1578
end
1679
end
1780

18-
defrecord Schema, major: 0, minor: 0, patch: 0, build: nil, source: nil
19-
defrecord Requirement, source: nil, matchspec: nil
20-
21-
import Kernel, except: [match?: 2]
22-
2381
@doc """
24-
Checks if the given specification matches the given version.
82+
Checks if the given version matches the specification.
2583
"""
26-
@spec match?(String.t | Mix.Version.Requirement.t, String.t | Schema.t) :: boolean
27-
def match?(spec, version) when is_binary(spec) do
28-
case Mix.Version.Parser.parse_requirement(spec) do
29-
{ :ok, spec } ->
30-
match?(spec, version)
84+
@spec match?(t, requirement) :: boolean
85+
def match?(version, requirement) when is_binary(requirement) do
86+
case Mix.Version.Parser.parse_requirement(requirement) do
87+
{ :ok, req } ->
88+
match?(version, req)
3189
{ :error, reason } ->
3290
raise InvalidRequirement, reason: reason
3391
end
3492
end
3593
36-
def match?(spec, version) when is_binary(version) do
37-
match?(spec, parse(version))
94+
def match?(version, requirement) when is_binary(version) do
95+
match?(parse(version), requirement)
3896
end
3997
40-
def match?(Requirement[matchspec: spec], Schema[] = version) do
98+
def match?(Schema[] = version, Requirement[matchspec: spec]) do
4199
case :ets.test_ms(to_matchable(version), spec) do
42100
{ :ok, result } ->
43101
result != false

lib/mix/test/mix/version_test.exs

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,56 +25,56 @@ defmodule Mix.VersionTest do
2525

2626
test "matches properly" do
2727
assert V.match?("2.3", "2.3")
28-
refute V.match?("2.3", "2.4")
28+
refute V.match?("2.4", "2.3")
2929

30-
assert V.match?("!2.3", "2.4")
31-
refute V.match?("!2.3", "2.3")
30+
assert V.match?("2.4", "!2.3")
31+
refute V.match?("2.3", "!2.3")
3232

33-
assert V.match?("> 2.3", "2.4")
34-
refute V.match?("> 2.3", "2.2")
35-
refute V.match?("> 2.3", "2.3")
33+
assert V.match?("2.4", "> 2.3")
34+
refute V.match?("2.2", "> 2.3")
35+
refute V.match?("2.3", "> 2.3")
3636

37-
assert V.match?(">= 2.3", "2.4")
38-
refute V.match?(">= 2.3", "2.2")
39-
assert V.match?(">= 2.3", "2.3")
37+
assert V.match?("2.4", ">= 2.3")
38+
refute V.match?("2.2", ">= 2.3")
39+
assert V.match?("2.3", ">= 2.3")
4040

41-
assert V.match?("< 2.3", "2.2")
42-
refute V.match?("< 2.3", "2.4")
43-
refute V.match?("< 2.3", "2.3")
41+
assert V.match?("2.2", "< 2.3")
42+
refute V.match?("2.4", "< 2.3")
43+
refute V.match?("2.3", "< 2.3")
4444

45-
assert V.match?("<= 2.3", "2.2")
46-
refute V.match?("<= 2.3", "2.4")
47-
assert V.match?("<= 2.3", "2.3")
45+
assert V.match?("2.2", "<= 2.3")
46+
refute V.match?("2.4", "<= 2.3")
47+
assert V.match?("2.3", "<= 2.3")
4848

49-
assert V.match?("~> 3.0", "3.0")
50-
assert V.match?("~> 3.0", "3.2")
51-
refute V.match?("~> 3.0", "4.0")
52-
refute V.match?("~> 3.0", "4.4")
49+
assert V.match?("3.0", "~> 3.0")
50+
assert V.match?("3.2", "~> 3.0")
51+
refute V.match?("4.0", "~> 3.0")
52+
refute V.match?("4.4", "~> 3.0")
5353

54-
assert V.match?("~> 3.0.0", "3.0.2")
55-
assert V.match?("~> 3.0.0", "3.0.0")
56-
refute V.match?("~> 3.0.0", "3.1")
57-
refute V.match?("~> 3.0.0", "3.4")
54+
assert V.match?("3.0.2", "~> 3.0.0")
55+
assert V.match?("3.0.0", "~> 3.0.0")
56+
refute V.match?("3.1", "~> 3.0.0")
57+
refute V.match?("3.4", "~> 3.0.0")
5858

59-
assert V.match?("~> 3.5", "3.6")
60-
assert V.match?("~> 3.5", "3.5")
61-
refute V.match?("~> 3.5", "4.0")
62-
refute V.match?("~> 3.5", "5.0")
59+
assert V.match?("3.6", "~> 3.5")
60+
assert V.match?("3.5", "~> 3.5")
61+
refute V.match?("4.0", "~> 3.5")
62+
refute V.match?("5.0", "~> 3.5")
6363

64-
assert V.match?("~> 3.5.0", "3.5.2")
65-
assert V.match?("~> 3.5.0", "3.5.4")
66-
refute V.match?("~> 3.5.0", "3.6")
67-
refute V.match?("~> 3.5.0", "3.6.3")
64+
assert V.match?("3.5.2", "~> 3.5.0")
65+
assert V.match?("3.5.4", "~> 3.5.0")
66+
refute V.match?("3.6", "~> 3.5.0")
67+
refute V.match?("3.6.3", "~> 3.5.0")
6868

6969
assert V.match?("1.0.0", "1.0.0")
70-
assert V.match?("1.0", "1.0.0")
71-
assert V.match?(">= 1.0", "2.0")
72-
assert V.match?(">= 1.0", "1.0.0")
70+
assert V.match?("1.0.0", "1.0")
71+
assert V.match?("2.0", ">= 1.0")
72+
assert V.match?("1.0.0", ">= 1.0")
7373

7474
assert V.match?("1.2.3-alpha", "1.2.3-alpha")
75-
refute V.match?("> 1.2.3-alpha", "1.2.3")
76-
assert V.match?("> 1.2.3-alpha", "1.2.3-alpha1")
77-
assert V.match?("> 1.2.3-alpha1", "1.2.3-alpha10")
75+
refute V.match?("1.2.3", "> 1.2.3-alpha")
76+
assert V.match?("1.2.3-alpha1", "> 1.2.3-alpha")
77+
assert V.match?("1.2.3-alpha10", "> 1.2.3-alpha1")
7878

7979
assert V.match?("iliketrains", "iliketrains")
8080
assert V.match?("1.2.3.4", "1.2.3.4")

0 commit comments

Comments
 (0)