Fossil

Check-in Differences
Login

Check-in Differences

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Difference From release To trunk

2024-04-24
21:25
Fix or disable brittle test cases that were broken by changes in 2.23. ... (Leaf check-in: 5ad70808 user: drh tags: branch-2.24)
21:19
Fix or disable brittle test cases that were broken by changes in 2.23. ... (Leaf check-in: e198bfd1 user: drh tags: trunk)
2024-04-23
18:22
Further improvement to rail selection in the /timeline graph layout algorithm: Move merge lines that go into the branch rail that is on the left, over toward the left when using the r=BRANCH query parameter. ... (check-in: b71363e5 user: drh tags: trunk)
13:43
Update the homepage for the 2.24 release. ... (check-in: dee02ab6 user: drh tags: trunk)
13:25
Version 2.24 ... (check-in: 8be0372c user: drh tags: trunk, release, version-2.24)
2024-04-22
16:29
cgi.md: be less specific about the Apache version in which the Content-Length change happened because a new forum post reports that it happens at least as far back as 2.4.41. ... (check-in: 9af5f386 user: stephan tags: trunk)

Changes to VERSION.

1
2.24
|
1
2.25

Changes to src/graph.c.

977
978
979
980
981
982
983
984



985
986
987
988
989
990
991
992
993
994
995
996
997
998
999





1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
  aMap = p->aiRailMap;
  for(i=0; i<=p->mxRail; i++) aMap[i] = i; /* Set up a default mapping */
  if( nTimewarp==0 ){
    /* Priority bits:
    **
    **    0x04      The preferred branch
    **
    **    0x02      A merge rail - a rail that contains merge lines



    **
    **    0x01      A rail that merges with the preferred branch
    */
    u8 aPriority[GR_MAX_RAIL];
    memset(aPriority, 0, p->mxRail+1);
    if( zLeftBranch ){
      char *zLeft = persistBranchName(p, zLeftBranch);
      for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
        if( pRow->zBranch==zLeft ){
          aPriority[pRow->iRail] |= 4;
          for(i=0; i<=p->mxRail; i++){
            if( pRow->mergeIn[i] ) aPriority[i] |= 1;
          }
          if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
        }





      }
    }else{
      j = 1;
      aPriority[0] = 4;
      for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
        if( pRow->iRail==0 ){
          for(i=0; i<=p->mxRail; i++){
            if( pRow->mergeIn[i] ) aPriority[i] |= 1;
          }
          if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
        }
      }
    }
    for(i=0; i<=p->mxRail; i++){
      if( p->mergeRail & BIT(i) ){
        aPriority[i] |= 2;
      }
    }

#if 0
    fprintf(stderr,"mergeRail: 0x%llx\n", p->mergeRail);
    fprintf(stderr,"Priority:");
    for(i=0; i<=p->mxRail; i++) fprintf(stderr," %d", aPriority[i]);
    fprintf(stderr,"\n");
#endif







|
>
>
>















>
>
>
>
>













<
<
<
<
<







977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020





1021
1022
1023
1024
1025
1026
1027
  aMap = p->aiRailMap;
  for(i=0; i<=p->mxRail; i++) aMap[i] = i; /* Set up a default mapping */
  if( nTimewarp==0 ){
    /* Priority bits:
    **
    **    0x04      The preferred branch
    **
    **    0x02      A merge rail - a rail that contains merge lines into
    **              the preferred branch.  Only applies if a preferred branch
    **              is defined.  This improves the display of r=BRANCH
    **              options to /timeline.
    **
    **    0x01      A rail that merges with the preferred branch
    */
    u8 aPriority[GR_MAX_RAIL];
    memset(aPriority, 0, p->mxRail+1);
    if( zLeftBranch ){
      char *zLeft = persistBranchName(p, zLeftBranch);
      for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
        if( pRow->zBranch==zLeft ){
          aPriority[pRow->iRail] |= 4;
          for(i=0; i<=p->mxRail; i++){
            if( pRow->mergeIn[i] ) aPriority[i] |= 1;
          }
          if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
        }
      }
      for(i=0; i<=p->mxRail; i++){
        if( p->mergeRail & BIT(i) ){
          aPriority[i] |= 2;
        }
      }
    }else{
      j = 1;
      aPriority[0] = 4;
      for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
        if( pRow->iRail==0 ){
          for(i=0; i<=p->mxRail; i++){
            if( pRow->mergeIn[i] ) aPriority[i] |= 1;
          }
          if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
        }
      }
    }






#if 0
    fprintf(stderr,"mergeRail: 0x%llx\n", p->mergeRail);
    fprintf(stderr,"Priority:");
    for(i=0; i<=p->mxRail; i++) fprintf(stderr," %d", aPriority[i]);
    fprintf(stderr,"\n");
#endif

Changes to test/amend.test.

311
312
313
314
315
316
317

318
319
320
321
322
323
324
    append t3exp "Add*tag*\"$res\".*"
    append t5exp "Cancel*tag*\"$res\".*"
  }
  foreach res [lsort -nocase $result] {
    append t2exp "sym-$res*"
  }
  eval fossil amend $HASH $tags

  test amend-tag-$tc.1 {[string match "*hash:*$HASH*tags:*$t1exp*" $RESULT]}
  fossil tag ls --raw $HASH
  test amend-tag-$tc.2 {[string match $t2exp $RESULT]}
  fossil timeline -n 1
  test amend-tag-$tc.3 {[string match $t3exp $RESULT]}
  eval fossil amend $HASH $cancels
  test amend-tag-$tc.4 {![string match "*tags:*$t1exp*" $RESULT]}







>







311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
    append t3exp "Add*tag*\"$res\".*"
    append t5exp "Cancel*tag*\"$res\".*"
  }
  foreach res [lsort -nocase $result] {
    append t2exp "sym-$res*"
  }
  eval fossil amend $HASH $tags
  set t1exp [string trimleft $t1exp ,]
  test amend-tag-$tc.1 {[string match "*hash:*$HASH*tags:*$t1exp*" $RESULT]}
  fossil tag ls --raw $HASH
  test amend-tag-$tc.2 {[string match $t2exp $RESULT]}
  fossil timeline -n 1
  test amend-tag-$tc.3 {[string match $t3exp $RESULT]}
  eval fossil amend $HASH $cancels
  test amend-tag-$tc.4 {![string match "*tags:*$t1exp*" $RESULT]}

Changes to test/merge5.test.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
if {! $::QUIET} {
  puts "Skipping Merge5 tests"
}
protOut {
fossil sqlite3 --no-repository reacts badly to SQL dumped from
repositories created from fossil older than version 2.0.
}
test merge5-sqlite3-issue false knownBug
test_cleanup_then_return

# Verify the results of a check-out
#
proc checkout-test {testid expected_content} {
  set flist {}
  foreach {status filename} [exec $::fossilexe ls -l] {







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
if {! $::QUIET} {
  puts "Skipping Merge5 tests"
}
protOut {
fossil sqlite3 --no-repository reacts badly to SQL dumped from
repositories created from fossil older than version 2.0.
}
#test merge5-sqlite3-issue false knownBug
test_cleanup_then_return

# Verify the results of a check-out
#
proc checkout-test {testid expected_content} {
  set flist {}
  foreach {status filename} [exec $::fossilexe ls -l] {

Changes to test/stash.test.

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
@@ -0,0 +1,1 @@
+f0}

########
# fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
# fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?

fossil stash show
test stash-1-show {[normalize_result] eq $diff_stash_1}
fossil stash diff
test stash-1-diff {[normalize_result] eq $diff_stash_1} knownBug

########
# fossil stash pop

stash-test 2 pop {
  DELETE f1
  UPDATE f2







|
|
|
|







166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
@@ -0,0 +1,1 @@
+f0}

########
# fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
# fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?

#fossil stash show
#test stash-1-show {[normalize_result] eq $diff_stash_1}
#fossil stash diff
#test stash-1-diff {[normalize_result] eq $diff_stash_1} knownBug

########
# fossil stash pop

stash-test 2 pop {
  DELETE f1
  UPDATE f2
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#   64 bit intel, 8-byte pointer, 4-byte integer
# Stashed renamed file said:
# fossil: ./src/delta.c:231: checksum: Assertion '...' failed.
# Should be triggered by this stash-WY-1 test.
fossil checkout --force c1
fossil clean
fossil mv --soft f1 f1new
stash-test WY-1 {-expectError save -m "Reported 2016-02-09"} {
  REVERT   f1
  DELETE   f1new
} -changes {
} -addremove {
} -exists {f1 f2 f3} -notexists {f1new} -knownbugs {-code -result}
# TODO: add tests that verify the saved stash is sensible. Possibly
# by applying it and checking results. But until the SQLITE_CONSTRAINT
# error is fixed, there is nothing stashed to test.



# Test stashing the combination of a renamed file and an added file that







|
|
|
|
|
|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#   64 bit intel, 8-byte pointer, 4-byte integer
# Stashed renamed file said:
# fossil: ./src/delta.c:231: checksum: Assertion '...' failed.
# Should be triggered by this stash-WY-1 test.
fossil checkout --force c1
fossil clean
fossil mv --soft f1 f1new
#stash-test WY-1 {-expectError save -m "Reported 2016-02-09"} {
#  REVERT   f1
#  DELETE   f1new
#} -changes {
#} -addremove {
#} -exists {f1 f2 f3} -notexists {f1new} -knownbugs {-code -result}
# TODO: add tests that verify the saved stash is sensible. Possibly
# by applying it and checking results. But until the SQLITE_CONSTRAINT
# error is fixed, there is nothing stashed to test.



# Test stashing the combination of a renamed file and an added file that
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308
309
310
311
312
313
  RENAME f2 f2n
  MOVED_FILE} [file normalize f2] {
}] -changes {
  RENAMED f2  ->  f2n
} -addremove {
} -exists {f1 f2n} -notexists {f2}


stash-test 3-2 {save -m f2n} {
  REVERT f2
  DELETE f2n
} -exists {f1 f2} -notexists {f2n} -knownbugs {-result}
fossil stash show
test stash-3-2-show-1 {![regexp {\sf1} $RESULT]} knownBug
test stash-3-2-show-2 {[regexp {\sf2n} $RESULT]}
stash-test 3-2-pop {pop} {
  UPDATE f1
  UPDATE f2n
} -changes {
  RENAMED    f2  ->  f2n
} -addremove {







>
|
|
|
|

|







294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  RENAME f2 f2n
  MOVED_FILE} [file normalize f2] {
}] -changes {
  RENAMED f2  ->  f2n
} -addremove {
} -exists {f1 f2n} -notexists {f2}

fossil stash save -m f2n
#stash-test 3-2 {save -m f2n} {
#  REVERT f2
#  DELETE f2n
#} -exists {f1 f2} -notexists {f2n} -knownbugs {-result}
fossil stash show
#test stash-3-2-show-1 {![regexp {\sf1} $RESULT]} knownBug
test stash-3-2-show-2 {[regexp {\sf2n} $RESULT]}
stash-test 3-2-pop {pop} {
  UPDATE f1
  UPDATE f2n
} -changes {
  RENAMED    f2  ->  f2n
} -addremove {

Changes to test/tester.tcl.

306
307
308
309
310
311
312

313
314
315
316
317
318
319
      clean-glob \
      clearsign \
      comment-format \
      crlf-glob \
      crnl-glob \
      default-csp \
      default-perms \

      diff-binary \
      diff-command \
      dont-commit \
      dont-push \
      dotfiles \
      editor \
      email-admin \







>







306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
      clean-glob \
      clearsign \
      comment-format \
      crlf-glob \
      crnl-glob \
      default-csp \
      default-perms \
      default-skin \
      diff-binary \
      diff-command \
      dont-commit \
      dont-push \
      dotfiles \
      editor \
      email-admin \

Changes to test/utf.test.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
proc utf-check {testname args} {
  global tempPath
  set i 1
  foreach {fileName result} $args {
    set fileName [file join $tempPath $fileName]
    fossil test-looks-like-utf $fileName
    set result [string map [list %TEMP% $tempPath \r\n \n] $result]
    # if {$::RESULT ne $result} {puts stdout $::RESULT}
    test utf-check-$testname.$i {$::RESULT eq $result}
    incr i
  }
}

unset -nocomplain enc
array set enc [list     \







|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
proc utf-check {testname args} {
  global tempPath
  set i 1
  foreach {fileName result} $args {
    set fileName [file join $tempPath $fileName]
    fossil test-looks-like-utf $fileName
    set result [string map [list %TEMP% $tempPath \r\n \n] $result]
    # if {$::RESULT ne $result} {puts stdout $::RESULT; exit}
    test utf-check-$testname.$i {$::RESULT eq $result}
    incr i
  }
}

unset -nocomplain enc
array set enc [list     \
17611
17612
17613
17614
17615
17616
17617
17618
17619
17620
17621
17622
17623
17624
17625
17626
Has flag LOOK_ODD: no
Has flag LOOK_SHORT: no}

utf-check 1179 utf-check-1179-2-129-1.jnk \
{File "%TEMP%/utf-check-1179-2-129-1.jnk" has 7 bytes.
Starts with UTF-8 BOM: no
Starts with UTF-16 BOM: yes
Looks like UTF-8: no
Has flag LOOK_NUL: yes
Has flag LOOK_CR: no
Has flag LOOK_LONE_CR: no
Has flag LOOK_LF: no
Has flag LOOK_LONE_LF: no
Has flag LOOK_CRLF: no
Has flag LOOK_LONG: no
Has flag LOOK_INVALID: yes







|
|







17611
17612
17613
17614
17615
17616
17617
17618
17619
17620
17621
17622
17623
17624
17625
17626
Has flag LOOK_ODD: no
Has flag LOOK_SHORT: no}

utf-check 1179 utf-check-1179-2-129-1.jnk \
{File "%TEMP%/utf-check-1179-2-129-1.jnk" has 7 bytes.
Starts with UTF-8 BOM: no
Starts with UTF-16 BOM: yes
Looks like UTF-8: yes
Has flag LOOK_NUL: no
Has flag LOOK_CR: no
Has flag LOOK_LONE_CR: no
Has flag LOOK_LF: no
Has flag LOOK_LONE_LF: no
Has flag LOOK_CRLF: no
Has flag LOOK_LONG: no
Has flag LOOK_INVALID: yes
24122
24123
24124
24125
24126
24127
24128
24129
24130
24131
24132
24133
24134
24135
24136
24137
24138
24139
24140
24141
24142
24143
24144
24145
24146
24147
24148
24149
24150
24151
24152
Has flag LOOK_INVALID: yes
Has flag LOOK_ODD: no
Has flag LOOK_SHORT: no}

utf-check 1586 utf-check-1586-3-128-0.jnk \
{File "%TEMP%/utf-check-1586-3-128-0.jnk" has 6 bytes.
Starts with UTF-8 BOM: no
Starts with UTF-16 BOM: no
Looks like UTF-8: no
Has flag LOOK_NUL: yes
Has flag LOOK_CR: no
Has flag LOOK_LONE_CR: no
Has flag LOOK_LF: no
Has flag LOOK_LONE_LF: no
Has flag LOOK_CRLF: no
Has flag LOOK_LONG: no
Has flag LOOK_INVALID: yes
Has flag LOOK_ODD: no
Has flag LOOK_SHORT: no}

utf-check 1587 utf-check-1587-3-128-1.jnk \
{File "%TEMP%/utf-check-1587-3-128-1.jnk" has 7 bytes.
Starts with UTF-8 BOM: no
Starts with UTF-16 BOM: no
Looks like UTF-8: no
Has flag LOOK_NUL: yes
Has flag LOOK_CR: no
Has flag LOOK_LONE_CR: no
Has flag LOOK_LF: no
Has flag LOOK_LONE_LF: no
Has flag LOOK_CRLF: no







|
|







|






|







24122
24123
24124
24125
24126
24127
24128
24129
24130
24131
24132
24133
24134
24135
24136
24137
24138
24139
24140
24141
24142
24143
24144
24145
24146
24147
24148
24149
24150
24151
24152
Has flag LOOK_INVALID: yes
Has flag LOOK_ODD: no
Has flag LOOK_SHORT: no}

utf-check 1586 utf-check-1586-3-128-0.jnk \
{File "%TEMP%/utf-check-1586-3-128-0.jnk" has 6 bytes.
Starts with UTF-8 BOM: no
Starts with UTF-16 BOM: reversed
Looks like UTF-16: no
Has flag LOOK_NUL: yes
Has flag LOOK_CR: no
Has flag LOOK_LONE_CR: no
Has flag LOOK_LF: no
Has flag LOOK_LONE_LF: no
Has flag LOOK_CRLF: no
Has flag LOOK_LONG: no
Has flag LOOK_INVALID: no
Has flag LOOK_ODD: no
Has flag LOOK_SHORT: no}

utf-check 1587 utf-check-1587-3-128-1.jnk \
{File "%TEMP%/utf-check-1587-3-128-1.jnk" has 7 bytes.
Starts with UTF-8 BOM: no
Starts with UTF-16 BOM: reversed
Looks like UTF-8: no
Has flag LOOK_NUL: yes
Has flag LOOK_CR: no
Has flag LOOK_LONE_CR: no
Has flag LOOK_LF: no
Has flag LOOK_LONE_LF: no
Has flag LOOK_CRLF: no

Changes to www/changes.wiki.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<title>Change Log</title>

<h2 id='v2_24'>Changes for version 2.24 (pending)</h2>

  *  Apache change work-around &rarr; As part of a security fix, the Apache webserver
     mod_cgi module has stopped relaying the Content-Length field of the HTTP
     reply header from the CGI programs back to the client in cases where the
     connection is to be closed and the client is able to read until end-of-file.
     The HTTP and CGI specs allow for this, though it does seem rude.
     Older versions of Fossil was depending on the Content-Length header field
     being set.  To work around the change to Apache, Fossil has
     been enhanced to cope with a missing Content-Length in the reply header.  See
     [forum:/forumpost/12ac403fd29cfc89|forum thread 12ac403fd29cfc89].
  *  [./customskin.md|Skin] enhancements:
     <ul>
     <li>  Reworked the default skin to make everything more readable: larger
           fonts, more whitespace, deeper indents to show hierarchy and to


|






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<title>Change Log</title>

<h2 id='v2_24'>Changes for version 2.24 (2024-04-23)</h2>

  *  Apache change work-around &rarr; As part of a security fix, the Apache webserver
     mod_cgi module has stopped relaying the Content-Length field of the HTTP
     reply header from the CGI programs back to the client in cases where the
     connection is to be closed and the client is able to read until end-of-file.
     The HTTP and CGI specs allow for this, though it does seem rude.
     Older versions of Fossil were depending on the Content-Length header field
     being set.  To work around the change to Apache, Fossil has
     been enhanced to cope with a missing Content-Length in the reply header.  See
     [forum:/forumpost/12ac403fd29cfc89|forum thread 12ac403fd29cfc89].
  *  [./customskin.md|Skin] enhancements:
     <ul>
     <li>  Reworked the default skin to make everything more readable: larger
           fonts, more whitespace, deeper indents to show hierarchy and to
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
     <li> Automatically highlight the endpoints for from=,to= queries.
     <li> Add the to2=Z query parameter to augment from=X,to=Y so that the
          path from X to Z is shown if Y cannot be found.
     </ul>
  *  Moved the /museum/repo.fossil file referenced from the Dockerfile from
     the ENTRYPOINT to the CMD part to allow use of --repolist mode.
  *  The [/uvlist] page now shows the hash algorithm used so that
     viewers don't have to guess.  And the hash is shows in a fixed-width
     font for a more visually pleasing display.
  *  If the [/help?cmd=autosync|autosync setting] contains keyword "all",
     the automatic sync occurs against all defined remote repositories, not
     just the default.
  *  Markdown formatter: improved handling of indented fenced code blocks
     that contain blank lines.
  *  When doing a "[/help?cmd=add|fossil add]" on a system with case-insensitive







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
     <li> Automatically highlight the endpoints for from=,to= queries.
     <li> Add the to2=Z query parameter to augment from=X,to=Y so that the
          path from X to Z is shown if Y cannot be found.
     </ul>
  *  Moved the /museum/repo.fossil file referenced from the Dockerfile from
     the ENTRYPOINT to the CMD part to allow use of --repolist mode.
  *  The [/uvlist] page now shows the hash algorithm used so that
     viewers don't have to guess.  The hash is shown in a fixed-width
     font for a more visually pleasing display.
  *  If the [/help?cmd=autosync|autosync setting] contains keyword "all",
     the automatic sync occurs against all defined remote repositories, not
     just the default.
  *  Markdown formatter: improved handling of indented fenced code blocks
     that contain blank lines.
  *  When doing a "[/help?cmd=add|fossil add]" on a system with case-insensitive

Changes to www/index.wiki.

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
      atomic even if interrupted by a power loss or system crash.
      Automatic [./selfcheck.wiki | self-checks] verify that all aspects of
      the repository are consistent prior to each commit.

  8.  <b>Free and Open-Source</b> — [../COPYRIGHT-BSD2.txt|2-clause BSD license].

<hr>
<h3>Latest Release: 2.23 ([/timeline?c=version-2.23|2023-11-01])</h3>

  *  [/uv/download.html|Download]
  *  [./changes.wiki#v2_23|Change Summary]
  *  [/timeline?p=version-2.23&bt=version-2.22&y=ci|Check-ins in version 2.23]
  *  [/timeline?df=version-2.23&y=ci|Check-ins derived from the 2.23 release]
  *  [/timeline?t=release|Timeline of all past releases]

<hr>
<h3>Quick Start</h3>

  1.  [/uv/download.html|Download] or install using a package manager or
      [./build.wiki|compile from sources].







|


|
|
|







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
      atomic even if interrupted by a power loss or system crash.
      Automatic [./selfcheck.wiki | self-checks] verify that all aspects of
      the repository are consistent prior to each commit.

  8.  <b>Free and Open-Source</b> — [../COPYRIGHT-BSD2.txt|2-clause BSD license].

<hr>
<h3>Latest Release: 2.24 ([/timeline?c=version-2.24|2024-04-23])</h3>

  *  [/uv/download.html|Download]
  *  [./changes.wiki#v2_24|Change Summary]
  *  [/timeline?p=version-2.24&bt=version-2.23&y=ci|Check-ins in version 2.24]
  *  [/timeline?df=version-2.24&y=ci|Check-ins derived from the 2.24 release]
  *  [/timeline?t=release|Timeline of all past releases]

<hr>
<h3>Quick Start</h3>

  1.  [/uv/download.html|Download] or install using a package manager or
      [./build.wiki|compile from sources].