diff options
| -rw-r--r-- | .editorconfig | 2 | ||||
| -rw-r--r-- | .gitattributes | 8 | ||||
| -rw-r--r-- | .github/workflows/coverity.yml | 2 | ||||
| -rw-r--r-- | .github/workflows/main.yml | 128 | ||||
| -rw-r--r-- | .gitignore | 4 | ||||
| -rw-r--r-- | .gitlab-ci.yml | 67 | ||||
| -rw-r--r-- | Documentation/.gitattributes | 1 | ||||
| -rw-r--r-- | Documentation/.gitignore | 8 | ||||
| -rw-r--r-- | Documentation/BreakingChanges.adoc (renamed from Documentation/BreakingChanges.txt) | 36 | ||||
| -rw-r--r-- | Documentation/CodingGuidelines | 4 | ||||
| -rw-r--r-- | Documentation/DecisionMaking.adoc (renamed from Documentation/DecisionMaking.txt) | 0 | ||||
| -rw-r--r-- | Documentation/Makefile | 209 | ||||
| -rw-r--r-- | Documentation/MyFirstContribution.adoc (renamed from Documentation/MyFirstContribution.txt) | 25 | ||||
| -rw-r--r-- | Documentation/MyFirstObjectWalk.adoc (renamed from Documentation/MyFirstObjectWalk.txt) | 14 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.0.1.adoc (renamed from Documentation/RelNotes/1.5.0.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.0.2.adoc (renamed from Documentation/RelNotes/1.5.0.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.0.3.adoc (renamed from Documentation/RelNotes/1.5.0.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.0.4.adoc (renamed from Documentation/RelNotes/1.5.0.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.0.5.adoc (renamed from Documentation/RelNotes/1.5.0.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.0.6.adoc (renamed from Documentation/RelNotes/1.5.0.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.0.7.adoc (renamed from Documentation/RelNotes/1.5.0.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.0.adoc (renamed from Documentation/RelNotes/1.5.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.1.1.adoc (renamed from Documentation/RelNotes/1.5.1.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.1.2.adoc (renamed from Documentation/RelNotes/1.5.1.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.1.3.adoc (renamed from Documentation/RelNotes/1.5.1.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.1.4.adoc (renamed from Documentation/RelNotes/1.5.1.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.1.5.adoc (renamed from Documentation/RelNotes/1.5.1.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.1.6.adoc (renamed from Documentation/RelNotes/1.5.1.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.1.adoc (renamed from Documentation/RelNotes/1.5.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.2.1.adoc (renamed from Documentation/RelNotes/1.5.2.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.2.2.adoc (renamed from Documentation/RelNotes/1.5.2.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.2.3.adoc (renamed from Documentation/RelNotes/1.5.2.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.2.4.adoc (renamed from Documentation/RelNotes/1.5.2.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.2.5.adoc (renamed from Documentation/RelNotes/1.5.2.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.2.adoc (renamed from Documentation/RelNotes/1.5.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.3.1.adoc (renamed from Documentation/RelNotes/1.5.3.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.3.2.adoc (renamed from Documentation/RelNotes/1.5.3.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.3.3.adoc (renamed from Documentation/RelNotes/1.5.3.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.3.4.adoc (renamed from Documentation/RelNotes/1.5.3.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.3.5.adoc (renamed from Documentation/RelNotes/1.5.3.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.3.6.adoc (renamed from Documentation/RelNotes/1.5.3.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.3.7.adoc (renamed from Documentation/RelNotes/1.5.3.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.3.8.adoc (renamed from Documentation/RelNotes/1.5.3.8.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.3.adoc (renamed from Documentation/RelNotes/1.5.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.4.1.adoc (renamed from Documentation/RelNotes/1.5.4.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.4.2.adoc (renamed from Documentation/RelNotes/1.5.4.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.4.3.adoc (renamed from Documentation/RelNotes/1.5.4.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.4.4.adoc (renamed from Documentation/RelNotes/1.5.4.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.4.5.adoc (renamed from Documentation/RelNotes/1.5.4.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.4.6.adoc (renamed from Documentation/RelNotes/1.5.4.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.4.7.adoc (renamed from Documentation/RelNotes/1.5.4.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.4.adoc (renamed from Documentation/RelNotes/1.5.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.5.1.adoc (renamed from Documentation/RelNotes/1.5.5.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.5.2.adoc (renamed from Documentation/RelNotes/1.5.5.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.5.3.adoc (renamed from Documentation/RelNotes/1.5.5.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.5.4.adoc (renamed from Documentation/RelNotes/1.5.5.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.5.5.adoc (renamed from Documentation/RelNotes/1.5.5.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.5.6.adoc (renamed from Documentation/RelNotes/1.5.5.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.5.adoc (renamed from Documentation/RelNotes/1.5.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.6.1.adoc (renamed from Documentation/RelNotes/1.5.6.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.6.2.adoc (renamed from Documentation/RelNotes/1.5.6.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.6.3.adoc (renamed from Documentation/RelNotes/1.5.6.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.6.4.adoc (renamed from Documentation/RelNotes/1.5.6.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.6.5.adoc (renamed from Documentation/RelNotes/1.5.6.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.6.6.adoc (renamed from Documentation/RelNotes/1.5.6.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.5.6.adoc (renamed from Documentation/RelNotes/1.5.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.0.1.adoc (renamed from Documentation/RelNotes/1.6.0.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.0.2.adoc (renamed from Documentation/RelNotes/1.6.0.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.0.3.adoc (renamed from Documentation/RelNotes/1.6.0.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.0.4.adoc (renamed from Documentation/RelNotes/1.6.0.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.0.5.adoc (renamed from Documentation/RelNotes/1.6.0.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.0.6.adoc (renamed from Documentation/RelNotes/1.6.0.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.0.adoc (renamed from Documentation/RelNotes/1.6.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.1.1.adoc (renamed from Documentation/RelNotes/1.6.1.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.1.2.adoc (renamed from Documentation/RelNotes/1.6.1.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.1.3.adoc (renamed from Documentation/RelNotes/1.6.1.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.1.4.adoc (renamed from Documentation/RelNotes/1.6.1.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.1.adoc (renamed from Documentation/RelNotes/1.6.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.2.1.adoc (renamed from Documentation/RelNotes/1.6.2.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.2.2.adoc (renamed from Documentation/RelNotes/1.6.2.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.2.3.adoc (renamed from Documentation/RelNotes/1.6.2.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.2.4.adoc (renamed from Documentation/RelNotes/1.6.2.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.2.5.adoc (renamed from Documentation/RelNotes/1.6.2.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.2.adoc (renamed from Documentation/RelNotes/1.6.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.3.1.adoc (renamed from Documentation/RelNotes/1.6.3.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.3.2.adoc (renamed from Documentation/RelNotes/1.6.3.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.3.3.adoc (renamed from Documentation/RelNotes/1.6.3.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.3.4.adoc (renamed from Documentation/RelNotes/1.6.3.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.3.adoc (renamed from Documentation/RelNotes/1.6.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.4.1.adoc (renamed from Documentation/RelNotes/1.6.4.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.4.2.adoc (renamed from Documentation/RelNotes/1.6.4.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.4.3.adoc (renamed from Documentation/RelNotes/1.6.4.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.4.4.adoc (renamed from Documentation/RelNotes/1.6.4.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.4.5.adoc (renamed from Documentation/RelNotes/1.6.4.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.4.adoc (renamed from Documentation/RelNotes/1.6.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.5.1.adoc (renamed from Documentation/RelNotes/1.6.5.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.5.2.adoc (renamed from Documentation/RelNotes/1.6.5.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.5.3.adoc (renamed from Documentation/RelNotes/1.6.5.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.5.4.adoc (renamed from Documentation/RelNotes/1.6.5.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.5.5.adoc (renamed from Documentation/RelNotes/1.6.5.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.5.6.adoc (renamed from Documentation/RelNotes/1.6.5.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.5.7.adoc (renamed from Documentation/RelNotes/1.6.5.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.5.8.adoc (renamed from Documentation/RelNotes/1.6.5.8.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.5.9.adoc (renamed from Documentation/RelNotes/1.6.5.9.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.5.adoc (renamed from Documentation/RelNotes/1.6.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.6.1.adoc (renamed from Documentation/RelNotes/1.6.6.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.6.2.adoc (renamed from Documentation/RelNotes/1.6.6.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.6.3.adoc (renamed from Documentation/RelNotes/1.6.6.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.6.6.adoc (renamed from Documentation/RelNotes/1.6.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.0.1.adoc (renamed from Documentation/RelNotes/1.7.0.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.0.2.adoc (renamed from Documentation/RelNotes/1.7.0.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.0.3.adoc (renamed from Documentation/RelNotes/1.7.0.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.0.4.adoc (renamed from Documentation/RelNotes/1.7.0.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.0.5.adoc (renamed from Documentation/RelNotes/1.7.0.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.0.6.adoc (renamed from Documentation/RelNotes/1.7.0.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.0.7.adoc (renamed from Documentation/RelNotes/1.7.0.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.0.8.adoc (renamed from Documentation/RelNotes/1.7.0.8.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.0.9.adoc (renamed from Documentation/RelNotes/1.7.0.9.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.0.adoc (renamed from Documentation/RelNotes/1.7.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.1.1.adoc (renamed from Documentation/RelNotes/1.7.1.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.1.2.adoc (renamed from Documentation/RelNotes/1.7.1.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.1.3.adoc (renamed from Documentation/RelNotes/1.7.1.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.1.4.adoc (renamed from Documentation/RelNotes/1.7.1.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.1.adoc (renamed from Documentation/RelNotes/1.7.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.10.1.adoc (renamed from Documentation/RelNotes/1.7.10.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.10.2.adoc (renamed from Documentation/RelNotes/1.7.10.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.10.3.adoc (renamed from Documentation/RelNotes/1.7.10.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.10.4.adoc (renamed from Documentation/RelNotes/1.7.10.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.10.5.adoc (renamed from Documentation/RelNotes/1.7.10.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.10.adoc (renamed from Documentation/RelNotes/1.7.10.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.11.1.adoc (renamed from Documentation/RelNotes/1.7.11.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.11.2.adoc (renamed from Documentation/RelNotes/1.7.11.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.11.3.adoc (renamed from Documentation/RelNotes/1.7.11.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.11.4.adoc (renamed from Documentation/RelNotes/1.7.11.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.11.5.adoc (renamed from Documentation/RelNotes/1.7.11.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.11.6.adoc (renamed from Documentation/RelNotes/1.7.11.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.11.7.adoc (renamed from Documentation/RelNotes/1.7.11.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.11.adoc (renamed from Documentation/RelNotes/1.7.11.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.12.1.adoc (renamed from Documentation/RelNotes/1.7.12.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.12.2.adoc (renamed from Documentation/RelNotes/1.7.12.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.12.3.adoc (renamed from Documentation/RelNotes/1.7.12.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.12.4.adoc (renamed from Documentation/RelNotes/1.7.12.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.12.adoc (renamed from Documentation/RelNotes/1.7.12.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.2.1.adoc (renamed from Documentation/RelNotes/1.7.2.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.2.2.adoc (renamed from Documentation/RelNotes/1.7.2.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.2.3.adoc (renamed from Documentation/RelNotes/1.7.2.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.2.4.adoc (renamed from Documentation/RelNotes/1.7.2.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.2.5.adoc (renamed from Documentation/RelNotes/1.7.2.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.2.adoc (renamed from Documentation/RelNotes/1.7.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.3.1.adoc (renamed from Documentation/RelNotes/1.7.3.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.3.2.adoc (renamed from Documentation/RelNotes/1.7.3.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.3.3.adoc (renamed from Documentation/RelNotes/1.7.3.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.3.4.adoc (renamed from Documentation/RelNotes/1.7.3.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.3.5.adoc (renamed from Documentation/RelNotes/1.7.3.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.3.adoc (renamed from Documentation/RelNotes/1.7.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.4.1.adoc (renamed from Documentation/RelNotes/1.7.4.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.4.2.adoc (renamed from Documentation/RelNotes/1.7.4.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.4.3.adoc (renamed from Documentation/RelNotes/1.7.4.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.4.4.adoc (renamed from Documentation/RelNotes/1.7.4.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.4.5.adoc (renamed from Documentation/RelNotes/1.7.4.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.4.adoc (renamed from Documentation/RelNotes/1.7.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.5.1.adoc (renamed from Documentation/RelNotes/1.7.5.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.5.2.adoc (renamed from Documentation/RelNotes/1.7.5.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.5.3.adoc (renamed from Documentation/RelNotes/1.7.5.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.5.4.adoc (renamed from Documentation/RelNotes/1.7.5.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.5.adoc (renamed from Documentation/RelNotes/1.7.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.6.1.adoc (renamed from Documentation/RelNotes/1.7.6.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.6.2.adoc (renamed from Documentation/RelNotes/1.7.6.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.6.3.adoc (renamed from Documentation/RelNotes/1.7.6.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.6.4.adoc (renamed from Documentation/RelNotes/1.7.6.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.6.5.adoc (renamed from Documentation/RelNotes/1.7.6.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.6.6.adoc (renamed from Documentation/RelNotes/1.7.6.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.6.adoc (renamed from Documentation/RelNotes/1.7.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.7.1.adoc (renamed from Documentation/RelNotes/1.7.7.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.7.2.adoc (renamed from Documentation/RelNotes/1.7.7.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.7.3.adoc (renamed from Documentation/RelNotes/1.7.7.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.7.4.adoc (renamed from Documentation/RelNotes/1.7.7.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.7.5.adoc (renamed from Documentation/RelNotes/1.7.7.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.7.6.adoc (renamed from Documentation/RelNotes/1.7.7.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.7.7.adoc (renamed from Documentation/RelNotes/1.7.7.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.7.adoc (renamed from Documentation/RelNotes/1.7.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.8.1.adoc (renamed from Documentation/RelNotes/1.7.8.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.8.2.adoc (renamed from Documentation/RelNotes/1.7.8.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.8.3.adoc (renamed from Documentation/RelNotes/1.7.8.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.8.4.adoc (renamed from Documentation/RelNotes/1.7.8.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.8.5.adoc (renamed from Documentation/RelNotes/1.7.8.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.8.6.adoc (renamed from Documentation/RelNotes/1.7.8.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.8.adoc (renamed from Documentation/RelNotes/1.7.8.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.9.1.adoc (renamed from Documentation/RelNotes/1.7.9.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.9.2.adoc (renamed from Documentation/RelNotes/1.7.9.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.9.3.adoc (renamed from Documentation/RelNotes/1.7.9.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.9.4.adoc (renamed from Documentation/RelNotes/1.7.9.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.9.5.adoc (renamed from Documentation/RelNotes/1.7.9.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.9.6.adoc (renamed from Documentation/RelNotes/1.7.9.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.9.7.adoc (renamed from Documentation/RelNotes/1.7.9.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.7.9.adoc (renamed from Documentation/RelNotes/1.7.9.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.0.1.adoc (renamed from Documentation/RelNotes/1.8.0.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.0.2.adoc (renamed from Documentation/RelNotes/1.8.0.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.0.3.adoc (renamed from Documentation/RelNotes/1.8.0.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.0.adoc (renamed from Documentation/RelNotes/1.8.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.1.1.adoc (renamed from Documentation/RelNotes/1.8.1.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.1.2.adoc (renamed from Documentation/RelNotes/1.8.1.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.1.3.adoc (renamed from Documentation/RelNotes/1.8.1.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.1.4.adoc (renamed from Documentation/RelNotes/1.8.1.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.1.5.adoc (renamed from Documentation/RelNotes/1.8.1.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.1.6.adoc (renamed from Documentation/RelNotes/1.8.1.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.1.adoc (renamed from Documentation/RelNotes/1.8.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.2.1.adoc (renamed from Documentation/RelNotes/1.8.2.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.2.2.adoc (renamed from Documentation/RelNotes/1.8.2.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.2.3.adoc (renamed from Documentation/RelNotes/1.8.2.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.2.adoc (renamed from Documentation/RelNotes/1.8.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.3.1.adoc (renamed from Documentation/RelNotes/1.8.3.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.3.2.adoc (renamed from Documentation/RelNotes/1.8.3.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.3.3.adoc (renamed from Documentation/RelNotes/1.8.3.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.3.4.adoc (renamed from Documentation/RelNotes/1.8.3.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.3.adoc (renamed from Documentation/RelNotes/1.8.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.4.1.adoc (renamed from Documentation/RelNotes/1.8.4.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.4.2.adoc (renamed from Documentation/RelNotes/1.8.4.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.4.3.adoc (renamed from Documentation/RelNotes/1.8.4.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.4.4.adoc (renamed from Documentation/RelNotes/1.8.4.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.4.5.adoc (renamed from Documentation/RelNotes/1.8.4.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.4.adoc (renamed from Documentation/RelNotes/1.8.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.5.1.adoc (renamed from Documentation/RelNotes/1.8.5.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.5.2.adoc (renamed from Documentation/RelNotes/1.8.5.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.5.3.adoc (renamed from Documentation/RelNotes/1.8.5.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.5.4.adoc (renamed from Documentation/RelNotes/1.8.5.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.5.5.adoc (renamed from Documentation/RelNotes/1.8.5.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.5.6.adoc (renamed from Documentation/RelNotes/1.8.5.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.8.5.adoc (renamed from Documentation/RelNotes/1.8.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.9.0.adoc (renamed from Documentation/RelNotes/1.9.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.9.1.adoc (renamed from Documentation/RelNotes/1.9.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.9.2.adoc (renamed from Documentation/RelNotes/1.9.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.9.3.adoc (renamed from Documentation/RelNotes/1.9.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.9.4.adoc (renamed from Documentation/RelNotes/1.9.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/1.9.5.adoc (renamed from Documentation/RelNotes/1.9.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.0.0.adoc (renamed from Documentation/RelNotes/2.0.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.0.1.adoc (renamed from Documentation/RelNotes/2.0.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.0.2.adoc (renamed from Documentation/RelNotes/2.0.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.0.3.adoc (renamed from Documentation/RelNotes/2.0.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.0.4.adoc (renamed from Documentation/RelNotes/2.0.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.0.5.adoc (renamed from Documentation/RelNotes/2.0.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.1.0.adoc (renamed from Documentation/RelNotes/2.1.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.1.1.adoc (renamed from Documentation/RelNotes/2.1.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.1.2.adoc (renamed from Documentation/RelNotes/2.1.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.1.3.adoc (renamed from Documentation/RelNotes/2.1.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.1.4.adoc (renamed from Documentation/RelNotes/2.1.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.10.0.adoc (renamed from Documentation/RelNotes/2.10.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.10.1.adoc (renamed from Documentation/RelNotes/2.10.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.10.2.adoc (renamed from Documentation/RelNotes/2.10.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.10.3.adoc (renamed from Documentation/RelNotes/2.10.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.10.4.adoc (renamed from Documentation/RelNotes/2.10.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.10.5.adoc (renamed from Documentation/RelNotes/2.10.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.11.0.adoc (renamed from Documentation/RelNotes/2.11.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.11.1.adoc (renamed from Documentation/RelNotes/2.11.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.11.2.adoc (renamed from Documentation/RelNotes/2.11.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.11.3.adoc (renamed from Documentation/RelNotes/2.11.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.11.4.adoc (renamed from Documentation/RelNotes/2.11.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.12.0.adoc (renamed from Documentation/RelNotes/2.12.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.12.1.adoc (renamed from Documentation/RelNotes/2.12.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.12.2.adoc (renamed from Documentation/RelNotes/2.12.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.12.3.adoc (renamed from Documentation/RelNotes/2.12.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.12.4.adoc (renamed from Documentation/RelNotes/2.12.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.12.5.adoc (renamed from Documentation/RelNotes/2.12.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.13.0.adoc (renamed from Documentation/RelNotes/2.13.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.13.1.adoc (renamed from Documentation/RelNotes/2.13.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.13.2.adoc (renamed from Documentation/RelNotes/2.13.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.13.3.adoc (renamed from Documentation/RelNotes/2.13.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.13.4.adoc (renamed from Documentation/RelNotes/2.13.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.13.5.adoc (renamed from Documentation/RelNotes/2.13.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.13.6.adoc (renamed from Documentation/RelNotes/2.13.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.13.7.adoc (renamed from Documentation/RelNotes/2.13.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.14.0.adoc (renamed from Documentation/RelNotes/2.14.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.14.1.adoc (renamed from Documentation/RelNotes/2.14.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.14.2.adoc (renamed from Documentation/RelNotes/2.14.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.14.3.adoc (renamed from Documentation/RelNotes/2.14.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.14.4.adoc (renamed from Documentation/RelNotes/2.14.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.14.5.adoc (renamed from Documentation/RelNotes/2.14.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.14.6.adoc (renamed from Documentation/RelNotes/2.14.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.15.0.adoc (renamed from Documentation/RelNotes/2.15.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.15.1.adoc (renamed from Documentation/RelNotes/2.15.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.15.2.adoc (renamed from Documentation/RelNotes/2.15.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.15.3.adoc (renamed from Documentation/RelNotes/2.15.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.15.4.adoc (renamed from Documentation/RelNotes/2.15.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.16.0.adoc (renamed from Documentation/RelNotes/2.16.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.16.1.adoc (renamed from Documentation/RelNotes/2.16.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.16.2.adoc (renamed from Documentation/RelNotes/2.16.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.16.3.adoc (renamed from Documentation/RelNotes/2.16.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.16.4.adoc (renamed from Documentation/RelNotes/2.16.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.16.5.adoc (renamed from Documentation/RelNotes/2.16.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.16.6.adoc (renamed from Documentation/RelNotes/2.16.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.17.0.adoc (renamed from Documentation/RelNotes/2.17.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.17.1.adoc (renamed from Documentation/RelNotes/2.17.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.17.2.adoc (renamed from Documentation/RelNotes/2.17.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.17.3.adoc (renamed from Documentation/RelNotes/2.17.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.17.4.adoc (renamed from Documentation/RelNotes/2.17.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.17.5.adoc (renamed from Documentation/RelNotes/2.17.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.17.6.adoc (renamed from Documentation/RelNotes/2.17.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.18.0.adoc (renamed from Documentation/RelNotes/2.18.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.18.1.adoc (renamed from Documentation/RelNotes/2.18.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.18.2.adoc (renamed from Documentation/RelNotes/2.18.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.18.3.adoc (renamed from Documentation/RelNotes/2.18.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.18.4.adoc (renamed from Documentation/RelNotes/2.18.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.18.5.adoc (renamed from Documentation/RelNotes/2.18.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.19.0.adoc (renamed from Documentation/RelNotes/2.19.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.19.1.adoc (renamed from Documentation/RelNotes/2.19.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.19.2.adoc (renamed from Documentation/RelNotes/2.19.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.19.3.adoc (renamed from Documentation/RelNotes/2.19.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.19.4.adoc (renamed from Documentation/RelNotes/2.19.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.19.5.adoc (renamed from Documentation/RelNotes/2.19.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.19.6.adoc (renamed from Documentation/RelNotes/2.19.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.2.0.adoc (renamed from Documentation/RelNotes/2.2.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.2.1.adoc (renamed from Documentation/RelNotes/2.2.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.2.2.adoc (renamed from Documentation/RelNotes/2.2.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.2.3.adoc (renamed from Documentation/RelNotes/2.2.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.20.0.adoc (renamed from Documentation/RelNotes/2.20.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.20.1.adoc (renamed from Documentation/RelNotes/2.20.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.20.2.adoc (renamed from Documentation/RelNotes/2.20.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.20.3.adoc (renamed from Documentation/RelNotes/2.20.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.20.4.adoc (renamed from Documentation/RelNotes/2.20.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.20.5.adoc (renamed from Documentation/RelNotes/2.20.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.21.0.adoc (renamed from Documentation/RelNotes/2.21.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.21.1.adoc (renamed from Documentation/RelNotes/2.21.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.21.2.adoc (renamed from Documentation/RelNotes/2.21.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.21.3.adoc (renamed from Documentation/RelNotes/2.21.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.21.4.adoc (renamed from Documentation/RelNotes/2.21.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.22.0.adoc (renamed from Documentation/RelNotes/2.22.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.22.1.adoc (renamed from Documentation/RelNotes/2.22.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.22.2.adoc (renamed from Documentation/RelNotes/2.22.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.22.3.adoc (renamed from Documentation/RelNotes/2.22.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.22.4.adoc (renamed from Documentation/RelNotes/2.22.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.22.5.adoc (renamed from Documentation/RelNotes/2.22.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.23.0.adoc (renamed from Documentation/RelNotes/2.23.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.23.1.adoc (renamed from Documentation/RelNotes/2.23.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.23.2.adoc (renamed from Documentation/RelNotes/2.23.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.23.3.adoc (renamed from Documentation/RelNotes/2.23.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.23.4.adoc (renamed from Documentation/RelNotes/2.23.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.24.0.adoc (renamed from Documentation/RelNotes/2.24.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.24.1.adoc (renamed from Documentation/RelNotes/2.24.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.24.2.adoc (renamed from Documentation/RelNotes/2.24.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.24.3.adoc (renamed from Documentation/RelNotes/2.24.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.24.4.adoc (renamed from Documentation/RelNotes/2.24.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.25.0.adoc (renamed from Documentation/RelNotes/2.25.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.25.1.adoc (renamed from Documentation/RelNotes/2.25.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.25.2.adoc (renamed from Documentation/RelNotes/2.25.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.25.3.adoc (renamed from Documentation/RelNotes/2.25.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.25.4.adoc (renamed from Documentation/RelNotes/2.25.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.25.5.adoc (renamed from Documentation/RelNotes/2.25.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.26.0.adoc (renamed from Documentation/RelNotes/2.26.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.26.1.adoc (renamed from Documentation/RelNotes/2.26.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.26.2.adoc (renamed from Documentation/RelNotes/2.26.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.26.3.adoc (renamed from Documentation/RelNotes/2.26.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.27.0.adoc (renamed from Documentation/RelNotes/2.27.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.27.1.adoc (renamed from Documentation/RelNotes/2.27.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.28.0.adoc (renamed from Documentation/RelNotes/2.28.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.28.1.adoc (renamed from Documentation/RelNotes/2.28.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.29.0.adoc (renamed from Documentation/RelNotes/2.29.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.29.1.adoc (renamed from Documentation/RelNotes/2.29.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.29.2.adoc (renamed from Documentation/RelNotes/2.29.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.29.3.adoc (renamed from Documentation/RelNotes/2.29.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.3.0.adoc (renamed from Documentation/RelNotes/2.3.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.3.1.adoc (renamed from Documentation/RelNotes/2.3.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.3.10.adoc (renamed from Documentation/RelNotes/2.3.10.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.3.2.adoc (renamed from Documentation/RelNotes/2.3.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.3.3.adoc (renamed from Documentation/RelNotes/2.3.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.3.4.adoc (renamed from Documentation/RelNotes/2.3.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.3.5.adoc (renamed from Documentation/RelNotes/2.3.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.3.6.adoc (renamed from Documentation/RelNotes/2.3.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.3.7.adoc (renamed from Documentation/RelNotes/2.3.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.3.8.adoc (renamed from Documentation/RelNotes/2.3.8.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.3.9.adoc (renamed from Documentation/RelNotes/2.3.9.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.30.0.adoc (renamed from Documentation/RelNotes/2.30.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.30.1.adoc (renamed from Documentation/RelNotes/2.30.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.30.2.adoc (renamed from Documentation/RelNotes/2.30.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.30.3.adoc (renamed from Documentation/RelNotes/2.30.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.30.4.adoc (renamed from Documentation/RelNotes/2.30.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.30.5.adoc (renamed from Documentation/RelNotes/2.30.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.30.6.adoc (renamed from Documentation/RelNotes/2.30.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.30.7.adoc (renamed from Documentation/RelNotes/2.30.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.30.8.adoc (renamed from Documentation/RelNotes/2.30.8.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.30.9.adoc (renamed from Documentation/RelNotes/2.30.9.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.31.0.adoc (renamed from Documentation/RelNotes/2.31.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.31.1.adoc (renamed from Documentation/RelNotes/2.31.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.31.2.adoc (renamed from Documentation/RelNotes/2.31.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.31.3.adoc (renamed from Documentation/RelNotes/2.31.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.31.4.adoc (renamed from Documentation/RelNotes/2.31.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.31.5.adoc (renamed from Documentation/RelNotes/2.31.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.31.6.adoc (renamed from Documentation/RelNotes/2.31.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.31.7.adoc (renamed from Documentation/RelNotes/2.31.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.31.8.adoc (renamed from Documentation/RelNotes/2.31.8.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.32.0.adoc (renamed from Documentation/RelNotes/2.32.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.32.1.adoc (renamed from Documentation/RelNotes/2.32.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.32.2.adoc (renamed from Documentation/RelNotes/2.32.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.32.3.adoc (renamed from Documentation/RelNotes/2.32.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.32.4.adoc (renamed from Documentation/RelNotes/2.32.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.32.5.adoc (renamed from Documentation/RelNotes/2.32.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.32.6.adoc (renamed from Documentation/RelNotes/2.32.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.32.7.adoc (renamed from Documentation/RelNotes/2.32.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.33.0.adoc (renamed from Documentation/RelNotes/2.33.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.33.1.adoc (renamed from Documentation/RelNotes/2.33.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.33.2.adoc (renamed from Documentation/RelNotes/2.33.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.33.3.adoc (renamed from Documentation/RelNotes/2.33.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.33.4.adoc (renamed from Documentation/RelNotes/2.33.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.33.5.adoc (renamed from Documentation/RelNotes/2.33.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.33.6.adoc (renamed from Documentation/RelNotes/2.33.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.33.7.adoc (renamed from Documentation/RelNotes/2.33.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.33.8.adoc (renamed from Documentation/RelNotes/2.33.8.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.34.0.adoc (renamed from Documentation/RelNotes/2.34.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.34.1.adoc (renamed from Documentation/RelNotes/2.34.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.34.2.adoc (renamed from Documentation/RelNotes/2.34.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.34.3.adoc (renamed from Documentation/RelNotes/2.34.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.34.4.adoc (renamed from Documentation/RelNotes/2.34.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.34.5.adoc (renamed from Documentation/RelNotes/2.34.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.34.6.adoc (renamed from Documentation/RelNotes/2.34.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.34.7.adoc (renamed from Documentation/RelNotes/2.34.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.34.8.adoc (renamed from Documentation/RelNotes/2.34.8.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.35.0.adoc (renamed from Documentation/RelNotes/2.35.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.35.1.adoc (renamed from Documentation/RelNotes/2.35.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.35.2.adoc (renamed from Documentation/RelNotes/2.35.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.35.3.adoc (renamed from Documentation/RelNotes/2.35.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.35.4.adoc (renamed from Documentation/RelNotes/2.35.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.35.5.adoc (renamed from Documentation/RelNotes/2.35.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.35.6.adoc (renamed from Documentation/RelNotes/2.35.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.35.7.adoc (renamed from Documentation/RelNotes/2.35.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.35.8.adoc (renamed from Documentation/RelNotes/2.35.8.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.36.0.adoc (renamed from Documentation/RelNotes/2.36.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.36.1.adoc (renamed from Documentation/RelNotes/2.36.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.36.2.adoc (renamed from Documentation/RelNotes/2.36.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.36.3.adoc (renamed from Documentation/RelNotes/2.36.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.36.4.adoc (renamed from Documentation/RelNotes/2.36.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.36.5.adoc (renamed from Documentation/RelNotes/2.36.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.36.6.adoc (renamed from Documentation/RelNotes/2.36.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.37.0.adoc (renamed from Documentation/RelNotes/2.37.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.37.1.adoc (renamed from Documentation/RelNotes/2.37.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.37.2.adoc (renamed from Documentation/RelNotes/2.37.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.37.3.adoc (renamed from Documentation/RelNotes/2.37.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.37.4.adoc (renamed from Documentation/RelNotes/2.37.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.37.5.adoc (renamed from Documentation/RelNotes/2.37.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.37.6.adoc (renamed from Documentation/RelNotes/2.37.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.37.7.adoc (renamed from Documentation/RelNotes/2.37.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.38.0.adoc (renamed from Documentation/RelNotes/2.38.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.38.1.adoc (renamed from Documentation/RelNotes/2.38.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.38.2.adoc (renamed from Documentation/RelNotes/2.38.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.38.3.adoc (renamed from Documentation/RelNotes/2.38.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.38.4.adoc (renamed from Documentation/RelNotes/2.38.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.38.5.adoc (renamed from Documentation/RelNotes/2.38.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.39.0.adoc (renamed from Documentation/RelNotes/2.39.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.39.1.adoc (renamed from Documentation/RelNotes/2.39.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.39.2.adoc (renamed from Documentation/RelNotes/2.39.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.39.3.adoc (renamed from Documentation/RelNotes/2.39.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.39.4.adoc (renamed from Documentation/RelNotes/2.39.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.39.5.adoc (renamed from Documentation/RelNotes/2.39.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.0.adoc (renamed from Documentation/RelNotes/2.4.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.1.adoc (renamed from Documentation/RelNotes/2.4.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.10.adoc (renamed from Documentation/RelNotes/2.4.10.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.11.adoc (renamed from Documentation/RelNotes/2.4.11.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.12.adoc (renamed from Documentation/RelNotes/2.4.12.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.2.adoc (renamed from Documentation/RelNotes/2.4.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.3.adoc (renamed from Documentation/RelNotes/2.4.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.4.adoc (renamed from Documentation/RelNotes/2.4.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.5.adoc (renamed from Documentation/RelNotes/2.4.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.6.adoc (renamed from Documentation/RelNotes/2.4.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.7.adoc (renamed from Documentation/RelNotes/2.4.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.8.adoc (renamed from Documentation/RelNotes/2.4.8.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.4.9.adoc (renamed from Documentation/RelNotes/2.4.9.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.40.0.adoc (renamed from Documentation/RelNotes/2.40.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.40.1.adoc (renamed from Documentation/RelNotes/2.40.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.40.2.adoc (renamed from Documentation/RelNotes/2.40.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.40.3.adoc (renamed from Documentation/RelNotes/2.40.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.40.4.adoc (renamed from Documentation/RelNotes/2.40.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.41.0.adoc (renamed from Documentation/RelNotes/2.41.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.41.1.adoc (renamed from Documentation/RelNotes/2.41.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.41.2.adoc (renamed from Documentation/RelNotes/2.41.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.41.3.adoc (renamed from Documentation/RelNotes/2.41.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.42.0.adoc (renamed from Documentation/RelNotes/2.42.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.42.1.adoc (renamed from Documentation/RelNotes/2.42.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.42.2.adoc (renamed from Documentation/RelNotes/2.42.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.42.3.adoc (renamed from Documentation/RelNotes/2.42.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.42.4.adoc (renamed from Documentation/RelNotes/2.42.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.43.0.adoc (renamed from Documentation/RelNotes/2.43.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.43.1.adoc (renamed from Documentation/RelNotes/2.43.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.43.2.adoc (renamed from Documentation/RelNotes/2.43.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.43.3.adoc (renamed from Documentation/RelNotes/2.43.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.43.4.adoc (renamed from Documentation/RelNotes/2.43.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.43.5.adoc (renamed from Documentation/RelNotes/2.43.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.43.6.adoc (renamed from Documentation/RelNotes/2.43.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.44.0.adoc (renamed from Documentation/RelNotes/2.44.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.44.1.adoc (renamed from Documentation/RelNotes/2.44.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.44.2.adoc (renamed from Documentation/RelNotes/2.44.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.44.3.adoc (renamed from Documentation/RelNotes/2.44.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.45.0.adoc (renamed from Documentation/RelNotes/2.45.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.45.1.adoc (renamed from Documentation/RelNotes/2.45.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.45.2.adoc (renamed from Documentation/RelNotes/2.45.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.45.3.adoc (renamed from Documentation/RelNotes/2.45.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.46.0.adoc (renamed from Documentation/RelNotes/2.46.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.46.1.adoc (renamed from Documentation/RelNotes/2.46.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.46.2.adoc (renamed from Documentation/RelNotes/2.46.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.46.3.adoc (renamed from Documentation/RelNotes/2.46.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.47.0.adoc (renamed from Documentation/RelNotes/2.47.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.47.1.adoc (renamed from Documentation/RelNotes/2.47.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.47.2.adoc (renamed from Documentation/RelNotes/2.47.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.48.0.adoc (renamed from Documentation/RelNotes/2.48.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.48.1.adoc (renamed from Documentation/RelNotes/2.48.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.49.0.adoc | 288 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.5.0.adoc (renamed from Documentation/RelNotes/2.5.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.5.1.adoc (renamed from Documentation/RelNotes/2.5.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.5.2.adoc (renamed from Documentation/RelNotes/2.5.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.5.3.adoc (renamed from Documentation/RelNotes/2.5.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.5.4.adoc (renamed from Documentation/RelNotes/2.5.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.5.5.adoc (renamed from Documentation/RelNotes/2.5.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.5.6.adoc (renamed from Documentation/RelNotes/2.5.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.50.0.adoc | 34 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.6.0.adoc (renamed from Documentation/RelNotes/2.6.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.6.1.adoc (renamed from Documentation/RelNotes/2.6.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.6.2.adoc (renamed from Documentation/RelNotes/2.6.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.6.3.adoc (renamed from Documentation/RelNotes/2.6.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.6.4.adoc (renamed from Documentation/RelNotes/2.6.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.6.5.adoc (renamed from Documentation/RelNotes/2.6.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.6.6.adoc (renamed from Documentation/RelNotes/2.6.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.6.7.adoc (renamed from Documentation/RelNotes/2.6.7.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.7.0.adoc (renamed from Documentation/RelNotes/2.7.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.7.1.adoc (renamed from Documentation/RelNotes/2.7.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.7.2.adoc (renamed from Documentation/RelNotes/2.7.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.7.3.adoc (renamed from Documentation/RelNotes/2.7.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.7.4.adoc (renamed from Documentation/RelNotes/2.7.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.7.5.adoc (renamed from Documentation/RelNotes/2.7.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.7.6.adoc (renamed from Documentation/RelNotes/2.7.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.8.0.adoc (renamed from Documentation/RelNotes/2.8.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.8.1.adoc (renamed from Documentation/RelNotes/2.8.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.8.2.adoc (renamed from Documentation/RelNotes/2.8.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.8.3.adoc (renamed from Documentation/RelNotes/2.8.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.8.4.adoc (renamed from Documentation/RelNotes/2.8.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.8.5.adoc (renamed from Documentation/RelNotes/2.8.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.8.6.adoc (renamed from Documentation/RelNotes/2.8.6.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.9.0.adoc (renamed from Documentation/RelNotes/2.9.0.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.9.1.adoc (renamed from Documentation/RelNotes/2.9.1.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.9.2.adoc (renamed from Documentation/RelNotes/2.9.2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.9.3.adoc (renamed from Documentation/RelNotes/2.9.3.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.9.4.adoc (renamed from Documentation/RelNotes/2.9.4.txt) | 0 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.9.5.adoc (renamed from Documentation/RelNotes/2.9.5.txt) | 0 | ||||
| -rw-r--r-- | Documentation/ReviewingGuidelines.adoc (renamed from Documentation/ReviewingGuidelines.txt) | 0 | ||||
| -rw-r--r-- | Documentation/ToolsForGit.adoc (renamed from Documentation/ToolsForGit.txt) | 1 | ||||
| -rw-r--r-- | Documentation/blame-options.adoc (renamed from Documentation/blame-options.txt) | 2 | ||||
| -rwxr-xr-x | Documentation/build-docdep.perl | 24 | ||||
| -rwxr-xr-x | Documentation/cmd-list.perl | 8 | ||||
| -rw-r--r-- | Documentation/config.adoc (renamed from Documentation/config.txt) | 186 | ||||
| -rw-r--r-- | Documentation/config/add.adoc (renamed from Documentation/config/add.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/advice.adoc (renamed from Documentation/config/advice.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/alias.adoc (renamed from Documentation/config/alias.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/am.adoc (renamed from Documentation/config/am.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/apply.adoc (renamed from Documentation/config/apply.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/attr.adoc (renamed from Documentation/config/attr.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/bitmap-pseudo-merge.adoc (renamed from Documentation/config/bitmap-pseudo-merge.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/blame.adoc (renamed from Documentation/config/blame.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/branch.adoc (renamed from Documentation/config/branch.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/browser.adoc (renamed from Documentation/config/browser.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/bundle.adoc (renamed from Documentation/config/bundle.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/checkout.adoc (renamed from Documentation/config/checkout.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/clean.adoc (renamed from Documentation/config/clean.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/clone.adoc (renamed from Documentation/config/clone.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/color.adoc (renamed from Documentation/config/color.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/column.adoc (renamed from Documentation/config/column.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/commit.adoc (renamed from Documentation/config/commit.txt) | 25 | ||||
| -rw-r--r-- | Documentation/config/commitgraph.adoc (renamed from Documentation/config/commitgraph.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/completion.adoc (renamed from Documentation/config/completion.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/core.adoc (renamed from Documentation/config/core.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/credential.adoc (renamed from Documentation/config/credential.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/diff.adoc (renamed from Documentation/config/diff.txt) | 2 | ||||
| -rw-r--r-- | Documentation/config/difftool.adoc (renamed from Documentation/config/difftool.txt) | 2 | ||||
| -rw-r--r-- | Documentation/config/extensions.adoc (renamed from Documentation/config/extensions.txt) | 2 | ||||
| -rw-r--r-- | Documentation/config/fastimport.adoc (renamed from Documentation/config/fastimport.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/feature.adoc (renamed from Documentation/config/feature.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/fetch.adoc (renamed from Documentation/config/fetch.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/filter.adoc (renamed from Documentation/config/filter.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/fmt-merge-msg.adoc (renamed from Documentation/config/fmt-merge-msg.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/format.adoc (renamed from Documentation/config/format.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/fsck.adoc (renamed from Documentation/config/fsck.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/fsmonitor--daemon.adoc (renamed from Documentation/config/fsmonitor--daemon.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/gc.adoc (renamed from Documentation/config/gc.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/gitcvs.adoc (renamed from Documentation/config/gitcvs.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/gitweb.adoc (renamed from Documentation/config/gitweb.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/gpg.adoc (renamed from Documentation/config/gpg.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/grep.adoc (renamed from Documentation/config/grep.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/gui.adoc (renamed from Documentation/config/gui.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/guitool.adoc (renamed from Documentation/config/guitool.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/help.adoc (renamed from Documentation/config/help.txt) | 9 | ||||
| -rw-r--r-- | Documentation/config/http.adoc (renamed from Documentation/config/http.txt) | 15 | ||||
| -rw-r--r-- | Documentation/config/i18n.adoc (renamed from Documentation/config/i18n.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/imap.adoc (renamed from Documentation/config/imap.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/includeif.adoc (renamed from Documentation/config/includeif.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/index.adoc (renamed from Documentation/config/index.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/init.adoc (renamed from Documentation/config/init.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/instaweb.adoc (renamed from Documentation/config/instaweb.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/interactive.adoc (renamed from Documentation/config/interactive.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/log.adoc (renamed from Documentation/config/log.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/lsrefs.adoc (renamed from Documentation/config/lsrefs.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/mailinfo.adoc (renamed from Documentation/config/mailinfo.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/mailmap.adoc (renamed from Documentation/config/mailmap.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/maintenance.adoc (renamed from Documentation/config/maintenance.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/man.adoc (renamed from Documentation/config/man.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/merge.adoc (renamed from Documentation/config/merge.txt) | 7 | ||||
| -rw-r--r-- | Documentation/config/mergetool.adoc (renamed from Documentation/config/mergetool.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/notes.adoc (renamed from Documentation/config/notes.txt) | 32 | ||||
| -rw-r--r-- | Documentation/config/pack.adoc (renamed from Documentation/config/pack.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/pager.adoc (renamed from Documentation/config/pager.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/pretty.adoc (renamed from Documentation/config/pretty.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/promisor.adoc | 30 | ||||
| -rw-r--r-- | Documentation/config/promisor.txt | 3 | ||||
| -rw-r--r-- | Documentation/config/protocol.adoc (renamed from Documentation/config/protocol.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/pull.adoc (renamed from Documentation/config/pull.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/push.adoc (renamed from Documentation/config/push.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/rebase.adoc (renamed from Documentation/config/rebase.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/receive.adoc (renamed from Documentation/config/receive.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/reftable.adoc (renamed from Documentation/config/reftable.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/remote.adoc (renamed from Documentation/config/remote.txt) | 22 | ||||
| -rw-r--r-- | Documentation/config/remotes.adoc (renamed from Documentation/config/remotes.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/repack.adoc (renamed from Documentation/config/repack.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/rerere.adoc (renamed from Documentation/config/rerere.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/revert.adoc (renamed from Documentation/config/revert.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/safe.adoc (renamed from Documentation/config/safe.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/sendemail.adoc (renamed from Documentation/config/sendemail.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/sequencer.adoc (renamed from Documentation/config/sequencer.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/showbranch.adoc (renamed from Documentation/config/showbranch.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/sparse.adoc (renamed from Documentation/config/sparse.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/splitindex.adoc (renamed from Documentation/config/splitindex.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/ssh.adoc (renamed from Documentation/config/ssh.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/stash.adoc (renamed from Documentation/config/stash.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/status.adoc (renamed from Documentation/config/status.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/submodule.adoc (renamed from Documentation/config/submodule.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/tag.adoc (renamed from Documentation/config/tag.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/tar.adoc (renamed from Documentation/config/tar.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/trace2.adoc (renamed from Documentation/config/trace2.txt) | 2 | ||||
| -rw-r--r-- | Documentation/config/trailer.adoc | 136 | ||||
| -rw-r--r-- | Documentation/config/transfer.adoc (renamed from Documentation/config/transfer.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/uploadarchive.adoc (renamed from Documentation/config/uploadarchive.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/uploadpack.adoc (renamed from Documentation/config/uploadpack.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/url.adoc (renamed from Documentation/config/url.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/user.adoc (renamed from Documentation/config/user.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/versionsort.adoc (renamed from Documentation/config/versionsort.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/web.adoc (renamed from Documentation/config/web.txt) | 0 | ||||
| -rw-r--r-- | Documentation/config/worktree.adoc (renamed from Documentation/config/worktree.txt) | 0 | ||||
| -rw-r--r-- | Documentation/date-formats.adoc (renamed from Documentation/date-formats.txt) | 0 | ||||
| -rw-r--r-- | Documentation/diff-format.adoc (renamed from Documentation/diff-format.txt) | 2 | ||||
| -rw-r--r-- | Documentation/diff-generate-patch.adoc (renamed from Documentation/diff-generate-patch.txt) | 0 | ||||
| -rw-r--r-- | Documentation/diff-options.adoc (renamed from Documentation/diff-options.txt) | 0 | ||||
| -rw-r--r-- | Documentation/everyday.adoco (renamed from Documentation/everyday.txto) | 0 | ||||
| -rw-r--r-- | Documentation/fetch-options.adoc (renamed from Documentation/fetch-options.txt) | 0 | ||||
| -rw-r--r-- | Documentation/fsck-msgids.adoc (renamed from Documentation/fsck-msgids.txt) | 14 | ||||
| -rw-r--r-- | Documentation/git-add.adoc (renamed from Documentation/git-add.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-am.adoc (renamed from Documentation/git-am.txt) | 6 | ||||
| -rw-r--r-- | Documentation/git-annotate.adoc (renamed from Documentation/git-annotate.txt) | 2 | ||||
| -rw-r--r-- | Documentation/git-apply.adoc (renamed from Documentation/git-apply.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-archimport.adoc (renamed from Documentation/git-archimport.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-archive.adoc (renamed from Documentation/git-archive.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-backfill.adoc | 71 | ||||
| -rw-r--r-- | Documentation/git-bisect-lk2009.adoc (renamed from Documentation/git-bisect-lk2009.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-bisect.adoc (renamed from Documentation/git-bisect.txt) | 1 | ||||
| -rw-r--r-- | Documentation/git-blame.adoc (renamed from Documentation/git-blame.txt) | 6 | ||||
| -rw-r--r-- | Documentation/git-branch.adoc (renamed from Documentation/git-branch.txt) | 6 | ||||
| -rw-r--r-- | Documentation/git-bugreport.adoc (renamed from Documentation/git-bugreport.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-bundle.adoc (renamed from Documentation/git-bundle.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-cat-file.adoc (renamed from Documentation/git-cat-file.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-check-attr.adoc (renamed from Documentation/git-check-attr.txt) | 6 | ||||
| -rw-r--r-- | Documentation/git-check-ignore.adoc (renamed from Documentation/git-check-ignore.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-check-mailmap.adoc (renamed from Documentation/git-check-mailmap.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-check-ref-format.adoc (renamed from Documentation/git-check-ref-format.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-checkout-index.adoc (renamed from Documentation/git-checkout-index.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-checkout.adoc (renamed from Documentation/git-checkout.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-cherry-pick.adoc (renamed from Documentation/git-cherry-pick.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-cherry.adoc (renamed from Documentation/git-cherry.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-citool.adoc (renamed from Documentation/git-citool.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-clean.adoc (renamed from Documentation/git-clean.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-clone.adoc (renamed from Documentation/git-clone.txt) | 36 | ||||
| -rw-r--r-- | Documentation/git-column.adoc (renamed from Documentation/git-column.txt) | 7 | ||||
| -rw-r--r-- | Documentation/git-commit-graph.adoc (renamed from Documentation/git-commit-graph.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-commit-tree.adoc (renamed from Documentation/git-commit-tree.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-commit.adoc (renamed from Documentation/git-commit.txt) | 297 | ||||
| -rw-r--r-- | Documentation/git-config.adoc (renamed from Documentation/git-config.txt) | 6 | ||||
| -rw-r--r-- | Documentation/git-count-objects.adoc (renamed from Documentation/git-count-objects.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-credential-cache--daemon.adoc (renamed from Documentation/git-credential-cache--daemon.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-credential-cache.adoc (renamed from Documentation/git-credential-cache.txt) | 17 | ||||
| -rw-r--r-- | Documentation/git-credential-store.adoc (renamed from Documentation/git-credential-store.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-credential.adoc (renamed from Documentation/git-credential.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-cvsexportcommit.adoc (renamed from Documentation/git-cvsexportcommit.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-cvsimport.adoc (renamed from Documentation/git-cvsimport.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-cvsserver.adoc (renamed from Documentation/git-cvsserver.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-daemon.adoc (renamed from Documentation/git-daemon.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-describe.adoc (renamed from Documentation/git-describe.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-diagnose.adoc (renamed from Documentation/git-diagnose.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-diff-files.adoc (renamed from Documentation/git-diff-files.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-diff-index.adoc (renamed from Documentation/git-diff-index.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-diff-pairs.adoc | 60 | ||||
| -rw-r--r-- | Documentation/git-diff-tree.adoc (renamed from Documentation/git-diff-tree.txt) | 8 | ||||
| -rw-r--r-- | Documentation/git-diff.adoc (renamed from Documentation/git-diff.txt) | 8 | ||||
| -rw-r--r-- | Documentation/git-difftool.adoc (renamed from Documentation/git-difftool.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-fast-export.adoc (renamed from Documentation/git-fast-export.txt) | 26 | ||||
| -rw-r--r-- | Documentation/git-fast-import.adoc (renamed from Documentation/git-fast-import.txt) | 24 | ||||
| -rw-r--r-- | Documentation/git-fetch-pack.adoc (renamed from Documentation/git-fetch-pack.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-fetch.adoc (renamed from Documentation/git-fetch.txt) | 12 | ||||
| -rw-r--r-- | Documentation/git-filter-branch.adoc (renamed from Documentation/git-filter-branch.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-fmt-merge-msg.adoc (renamed from Documentation/git-fmt-merge-msg.txt) | 2 | ||||
| -rw-r--r-- | Documentation/git-for-each-ref.adoc (renamed from Documentation/git-for-each-ref.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-for-each-repo.adoc (renamed from Documentation/git-for-each-repo.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-format-patch.adoc (renamed from Documentation/git-format-patch.txt) | 2 | ||||
| -rw-r--r-- | Documentation/git-fsck-objects.adoc (renamed from Documentation/git-fsck-objects.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-fsck.adoc (renamed from Documentation/git-fsck.txt) | 13 | ||||
| -rw-r--r-- | Documentation/git-fsmonitor--daemon.adoc (renamed from Documentation/git-fsmonitor--daemon.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-gc.adoc (renamed from Documentation/git-gc.txt) | 11 | ||||
| -rw-r--r-- | Documentation/git-get-tar-commit-id.adoc (renamed from Documentation/git-get-tar-commit-id.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-grep.adoc (renamed from Documentation/git-grep.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-gui.adoc (renamed from Documentation/git-gui.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-hash-object.adoc (renamed from Documentation/git-hash-object.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-help.adoc (renamed from Documentation/git-help.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-hook.adoc (renamed from Documentation/git-hook.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-http-backend.adoc (renamed from Documentation/git-http-backend.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-http-fetch.adoc (renamed from Documentation/git-http-fetch.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-http-push.adoc (renamed from Documentation/git-http-push.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-imap-send.adoc (renamed from Documentation/git-imap-send.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-index-pack.adoc (renamed from Documentation/git-index-pack.txt) | 2 | ||||
| -rw-r--r-- | Documentation/git-init-db.adoc (renamed from Documentation/git-init-db.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-init.adoc (renamed from Documentation/git-init.txt) | 8 | ||||
| -rw-r--r-- | Documentation/git-instaweb.adoc (renamed from Documentation/git-instaweb.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-interpret-trailers.adoc (renamed from Documentation/git-interpret-trailers.txt) | 137 | ||||
| -rw-r--r-- | Documentation/git-log.adoc (renamed from Documentation/git-log.txt) | 20 | ||||
| -rw-r--r-- | Documentation/git-ls-files.adoc (renamed from Documentation/git-ls-files.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-ls-remote.adoc (renamed from Documentation/git-ls-remote.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-ls-tree.adoc (renamed from Documentation/git-ls-tree.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-mailinfo.adoc (renamed from Documentation/git-mailinfo.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-mailsplit.adoc (renamed from Documentation/git-mailsplit.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-maintenance.adoc (renamed from Documentation/git-maintenance.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-merge-base.adoc (renamed from Documentation/git-merge-base.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-merge-file.adoc (renamed from Documentation/git-merge-file.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-merge-index.adoc (renamed from Documentation/git-merge-index.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-merge-one-file.adoc (renamed from Documentation/git-merge-one-file.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-merge-tree.adoc (renamed from Documentation/git-merge-tree.txt) | 11 | ||||
| -rw-r--r-- | Documentation/git-merge.adoc (renamed from Documentation/git-merge.txt) | 10 | ||||
| -rw-r--r-- | Documentation/git-mergetool--lib.adoc (renamed from Documentation/git-mergetool--lib.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-mergetool.adoc (renamed from Documentation/git-mergetool.txt) | 6 | ||||
| -rw-r--r-- | Documentation/git-mktag.adoc (renamed from Documentation/git-mktag.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-mktree.adoc (renamed from Documentation/git-mktree.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-multi-pack-index.adoc (renamed from Documentation/git-multi-pack-index.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-mv.adoc (renamed from Documentation/git-mv.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-name-rev.adoc (renamed from Documentation/git-name-rev.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-notes.adoc (renamed from Documentation/git-notes.txt) | 195 | ||||
| -rw-r--r-- | Documentation/git-p4.adoc (renamed from Documentation/git-p4.txt) | 14 | ||||
| -rw-r--r-- | Documentation/git-pack-objects.adoc (renamed from Documentation/git-pack-objects.txt) | 32 | ||||
| -rw-r--r-- | Documentation/git-pack-redundant.adoc (renamed from Documentation/git-pack-redundant.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-pack-refs.adoc (renamed from Documentation/git-pack-refs.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-patch-id.adoc (renamed from Documentation/git-patch-id.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-prune-packed.adoc (renamed from Documentation/git-prune-packed.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-prune.adoc (renamed from Documentation/git-prune.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-pull.adoc (renamed from Documentation/git-pull.txt) | 12 | ||||
| -rw-r--r-- | Documentation/git-push.adoc (renamed from Documentation/git-push.txt) | 8 | ||||
| -rw-r--r-- | Documentation/git-quiltimport.adoc (renamed from Documentation/git-quiltimport.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-range-diff.adoc (renamed from Documentation/git-range-diff.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-read-tree.adoc (renamed from Documentation/git-read-tree.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-rebase.adoc (renamed from Documentation/git-rebase.txt) | 21 | ||||
| -rw-r--r-- | Documentation/git-receive-pack.adoc (renamed from Documentation/git-receive-pack.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-reflog.adoc (renamed from Documentation/git-reflog.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-refs.adoc (renamed from Documentation/git-refs.txt) | 13 | ||||
| -rw-r--r-- | Documentation/git-remote-ext.adoc (renamed from Documentation/git-remote-ext.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-remote-fd.adoc (renamed from Documentation/git-remote-fd.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-remote-helpers.adoco (renamed from Documentation/git-remote-helpers.txto) | 0 | ||||
| -rw-r--r-- | Documentation/git-remote.adoc (renamed from Documentation/git-remote.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-repack.adoc (renamed from Documentation/git-repack.txt) | 9 | ||||
| -rw-r--r-- | Documentation/git-replace.adoc (renamed from Documentation/git-replace.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-replay.adoc (renamed from Documentation/git-replay.txt) | 2 | ||||
| -rw-r--r-- | Documentation/git-request-pull.adoc (renamed from Documentation/git-request-pull.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-rerere.adoc (renamed from Documentation/git-rerere.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-reset.adoc (renamed from Documentation/git-reset.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-restore.adoc (renamed from Documentation/git-restore.txt) | 110 | ||||
| -rw-r--r-- | Documentation/git-rev-list.adoc (renamed from Documentation/git-rev-list.txt) | 6 | ||||
| -rw-r--r-- | Documentation/git-rev-parse.adoc (renamed from Documentation/git-rev-parse.txt) | 2 | ||||
| -rw-r--r-- | Documentation/git-revert.adoc (renamed from Documentation/git-revert.txt) | 8 | ||||
| -rw-r--r-- | Documentation/git-rm.adoc (renamed from Documentation/git-rm.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-send-email.adoc (renamed from Documentation/git-send-email.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-send-pack.adoc (renamed from Documentation/git-send-pack.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-sh-i18n--envsubst.adoc (renamed from Documentation/git-sh-i18n--envsubst.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-sh-i18n.adoc (renamed from Documentation/git-sh-i18n.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-sh-setup.adoc (renamed from Documentation/git-sh-setup.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-shell.adoc (renamed from Documentation/git-shell.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-shortlog.adoc (renamed from Documentation/git-shortlog.txt) | 2 | ||||
| -rw-r--r-- | Documentation/git-show-branch.adoc (renamed from Documentation/git-show-branch.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-show-index.adoc (renamed from Documentation/git-show-index.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-show-ref.adoc (renamed from Documentation/git-show-ref.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-show.adoc (renamed from Documentation/git-show.txt) | 10 | ||||
| -rw-r--r-- | Documentation/git-sparse-checkout.adoc (renamed from Documentation/git-sparse-checkout.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-stage.adoc (renamed from Documentation/git-stage.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-stash.adoc (renamed from Documentation/git-stash.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-status.adoc (renamed from Documentation/git-status.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-stripspace.adoc (renamed from Documentation/git-stripspace.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-submodule.adoc (renamed from Documentation/git-submodule.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-svn.adoc (renamed from Documentation/git-svn.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-switch.adoc (renamed from Documentation/git-switch.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-symbolic-ref.adoc (renamed from Documentation/git-symbolic-ref.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-tag.adoc (renamed from Documentation/git-tag.txt) | 4 | ||||
| -rw-r--r-- | Documentation/git-tools.adoc (renamed from Documentation/git-tools.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-unpack-file.adoc (renamed from Documentation/git-unpack-file.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-unpack-objects.adoc (renamed from Documentation/git-unpack-objects.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-update-index.adoc (renamed from Documentation/git-update-index.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-update-ref.adoc (renamed from Documentation/git-update-ref.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-update-server-info.adoc (renamed from Documentation/git-update-server-info.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-upload-archive.adoc (renamed from Documentation/git-upload-archive.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-upload-pack.adoc (renamed from Documentation/git-upload-pack.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-var.adoc (renamed from Documentation/git-var.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-verify-commit.adoc (renamed from Documentation/git-verify-commit.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-verify-pack.adoc (renamed from Documentation/git-verify-pack.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-verify-tag.adoc (renamed from Documentation/git-verify-tag.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-version.adoc (renamed from Documentation/git-version.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-web--browse.adoc (renamed from Documentation/git-web--browse.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-whatchanged.adoc (renamed from Documentation/git-whatchanged.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-worktree.adoc (renamed from Documentation/git-worktree.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git-write-tree.adoc (renamed from Documentation/git-write-tree.txt) | 0 | ||||
| -rw-r--r-- | Documentation/git.adoc (renamed from Documentation/git.txt) | 29 | ||||
| -rw-r--r-- | Documentation/gitattributes.adoc (renamed from Documentation/gitattributes.txt) | 36 | ||||
| -rw-r--r-- | Documentation/gitcli.adoc (renamed from Documentation/gitcli.txt) | 19 | ||||
| -rw-r--r-- | Documentation/gitcore-tutorial.adoc (renamed from Documentation/gitcore-tutorial.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitcredentials.adoc (renamed from Documentation/gitcredentials.txt) | 41 | ||||
| -rw-r--r-- | Documentation/gitcvs-migration.adoc (renamed from Documentation/gitcvs-migration.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitdiffcore.adoc (renamed from Documentation/gitdiffcore.txt) | 0 | ||||
| -rw-r--r-- | Documentation/giteveryday.adoc (renamed from Documentation/giteveryday.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitfaq.adoc (renamed from Documentation/gitfaq.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitformat-bundle.adoc (renamed from Documentation/gitformat-bundle.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitformat-chunk.adoc (renamed from Documentation/gitformat-chunk.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitformat-commit-graph.adoc (renamed from Documentation/gitformat-commit-graph.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitformat-index.adoc (renamed from Documentation/gitformat-index.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitformat-pack.adoc (renamed from Documentation/gitformat-pack.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitformat-signature.adoc (renamed from Documentation/gitformat-signature.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitglossary.adoc (renamed from Documentation/gitglossary.txt) | 2 | ||||
| -rw-r--r-- | Documentation/githooks.adoc (renamed from Documentation/githooks.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitignore.adoc (renamed from Documentation/gitignore.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitk.adoc (renamed from Documentation/gitk.txt) | 2 | ||||
| -rw-r--r-- | Documentation/gitmailmap.adoc (renamed from Documentation/gitmailmap.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitmodules.adoc (renamed from Documentation/gitmodules.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitnamespaces.adoc (renamed from Documentation/gitnamespaces.txt) | 2 | ||||
| -rw-r--r-- | Documentation/gitpacking.adoc (renamed from Documentation/gitpacking.txt) | 2 | ||||
| -rw-r--r-- | Documentation/gitprotocol-capabilities.adoc (renamed from Documentation/gitprotocol-capabilities.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitprotocol-common.adoc (renamed from Documentation/gitprotocol-common.txt) | 2 | ||||
| -rw-r--r-- | Documentation/gitprotocol-http.adoc (renamed from Documentation/gitprotocol-http.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitprotocol-pack.adoc (renamed from Documentation/gitprotocol-pack.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitprotocol-v2.adoc (renamed from Documentation/gitprotocol-v2.txt) | 64 | ||||
| -rw-r--r-- | Documentation/gitremote-helpers.adoc (renamed from Documentation/gitremote-helpers.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitrepository-layout.adoc (renamed from Documentation/gitrepository-layout.txt) | 13 | ||||
| -rw-r--r-- | Documentation/gitrevisions.adoc (renamed from Documentation/gitrevisions.txt) | 2 | ||||
| -rw-r--r-- | Documentation/gitsubmodules.adoc (renamed from Documentation/gitsubmodules.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gittutorial-2.adoc (renamed from Documentation/gittutorial-2.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gittutorial.adoc (renamed from Documentation/gittutorial.txt) | 0 | ||||
| -rw-r--r-- | Documentation/gitweb.adoc (renamed from Documentation/gitweb.txt) | 11 | ||||
| -rw-r--r-- | Documentation/gitweb.conf.adoc (renamed from Documentation/gitweb.conf.txt) | 2 | ||||
| -rw-r--r-- | Documentation/gitworkflows.adoc (renamed from Documentation/gitworkflows.txt) | 0 | ||||
| -rw-r--r-- | Documentation/glossary-content.adoc (renamed from Documentation/glossary-content.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/coordinate-embargoed-releases.adoc (renamed from Documentation/howto/coordinate-embargoed-releases.txt) | 0 | ||||
| -rwxr-xr-x | Documentation/howto/howto-index.sh | 14 | ||||
| -rw-r--r-- | Documentation/howto/keep-canonical-history-correct.adoc (renamed from Documentation/howto/keep-canonical-history-correct.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/maintain-git.adoc (renamed from Documentation/howto/maintain-git.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/meson.build | 36 | ||||
| -rw-r--r-- | Documentation/howto/new-command.adoc (renamed from Documentation/howto/new-command.txt) | 2 | ||||
| -rw-r--r-- | Documentation/howto/rebase-from-internal-branch.adoc (renamed from Documentation/howto/rebase-from-internal-branch.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/rebuild-from-update-hook.adoc (renamed from Documentation/howto/rebuild-from-update-hook.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/recover-corrupted-blob-object.adoc (renamed from Documentation/howto/recover-corrupted-blob-object.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/recover-corrupted-object-harder.adoc (renamed from Documentation/howto/recover-corrupted-object-harder.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/revert-a-faulty-merge.adoc (renamed from Documentation/howto/revert-a-faulty-merge.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/revert-branch-rebase.adoc (renamed from Documentation/howto/revert-branch-rebase.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/separating-topic-branches.adoc (renamed from Documentation/howto/separating-topic-branches.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/setup-git-server-over-http.adoc (renamed from Documentation/howto/setup-git-server-over-http.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/update-hook-example.adoc (renamed from Documentation/howto/update-hook-example.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/use-git-daemon.adoc (renamed from Documentation/howto/use-git-daemon.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/using-merge-subtree.adoc (renamed from Documentation/howto/using-merge-subtree.txt) | 0 | ||||
| -rw-r--r-- | Documentation/howto/using-signed-tag-in-pull-request.adoc (renamed from Documentation/howto/using-signed-tag-in-pull-request.txt) | 0 | ||||
| -rw-r--r-- | Documentation/i18n.adoc (renamed from Documentation/i18n.txt) | 4 | ||||
| -rw-r--r-- | Documentation/includes/cmd-config-section-all.adoc (renamed from Documentation/includes/cmd-config-section-all.txt) | 0 | ||||
| -rw-r--r-- | Documentation/includes/cmd-config-section-rest.adoc (renamed from Documentation/includes/cmd-config-section-rest.txt) | 0 | ||||
| -rwxr-xr-x | Documentation/install-webdoc.sh | 16 | ||||
| -rw-r--r-- | Documentation/line-range-format.adoc (renamed from Documentation/line-range-format.txt) | 0 | ||||
| -rw-r--r-- | Documentation/line-range-options.adoc (renamed from Documentation/line-range-options.txt) | 2 | ||||
| -rwxr-xr-x | Documentation/lint-gitlink.perl | 4 | ||||
| -rwxr-xr-x | Documentation/lint-manpages.sh | 6 | ||||
| -rw-r--r-- | Documentation/merge-options.adoc (renamed from Documentation/merge-options.txt) | 2 | ||||
| -rw-r--r-- | Documentation/merge-strategies.adoc (renamed from Documentation/merge-strategies.txt) | 24 | ||||
| -rw-r--r-- | Documentation/mergetools/vimdiff.adoc (renamed from Documentation/mergetools/vimdiff.txt) | 0 | ||||
| -rw-r--r-- | Documentation/meson.build | 470 | ||||
| -rw-r--r-- | Documentation/object-format-disclaimer.adoc (renamed from Documentation/object-format-disclaimer.txt) | 0 | ||||
| -rw-r--r-- | Documentation/pretty-formats.adoc (renamed from Documentation/pretty-formats.txt) | 8 | ||||
| -rw-r--r-- | Documentation/pretty-options.adoc (renamed from Documentation/pretty-options.txt) | 0 | ||||
| -rw-r--r-- | Documentation/pull-fetch-param.adoc (renamed from Documentation/pull-fetch-param.txt) | 0 | ||||
| -rw-r--r-- | Documentation/ref-reachability-filters.adoc (renamed from Documentation/ref-reachability-filters.txt) | 0 | ||||
| -rw-r--r-- | Documentation/ref-storage-format.adoc (renamed from Documentation/ref-storage-format.txt) | 0 | ||||
| -rw-r--r-- | Documentation/rerere-options.adoc (renamed from Documentation/rerere-options.txt) | 0 | ||||
| -rw-r--r-- | Documentation/rev-list-description.adoc (renamed from Documentation/rev-list-description.txt) | 0 | ||||
| -rw-r--r-- | Documentation/rev-list-options.adoc (renamed from Documentation/rev-list-options.txt) | 23 | ||||
| -rw-r--r-- | Documentation/revisions.adoc (renamed from Documentation/revisions.txt) | 0 | ||||
| -rw-r--r-- | Documentation/scalar.adoc (renamed from Documentation/scalar.txt) | 0 | ||||
| -rw-r--r-- | Documentation/sequencer.adoc (renamed from Documentation/sequencer.txt) | 0 | ||||
| -rw-r--r-- | Documentation/signoff-option.adoc (renamed from Documentation/signoff-option.txt) | 8 | ||||
| -rw-r--r-- | Documentation/technical/.gitignore | 1 | ||||
| -rw-r--r-- | Documentation/technical/api-error-handling.adoc (renamed from Documentation/technical/api-error-handling.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/api-index-skel.adoc (renamed from Documentation/technical/api-index-skel.txt) | 0 | ||||
| -rwxr-xr-x | Documentation/technical/api-index.sh | 8 | ||||
| -rw-r--r-- | Documentation/technical/api-merge.adoc (renamed from Documentation/technical/api-merge.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/api-parse-options.adoc (renamed from Documentation/technical/api-parse-options.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/api-path-walk.adoc | 72 | ||||
| -rw-r--r-- | Documentation/technical/api-simple-ipc.adoc (renamed from Documentation/technical/api-simple-ipc.txt) | 2 | ||||
| -rw-r--r-- | Documentation/technical/api-trace2.adoc (renamed from Documentation/technical/api-trace2.txt) | 2 | ||||
| -rw-r--r-- | Documentation/technical/bitmap-format.adoc (renamed from Documentation/technical/bitmap-format.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/build-systems.adoc (renamed from Documentation/technical/build-systems.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/bundle-uri.adoc (renamed from Documentation/technical/bundle-uri.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/commit-graph.adoc (renamed from Documentation/technical/commit-graph.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/directory-rename-detection.adoc (renamed from Documentation/technical/directory-rename-detection.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/hash-function-transition.adoc (renamed from Documentation/technical/hash-function-transition.txt) | 2 | ||||
| -rw-r--r-- | Documentation/technical/large-object-promisors.adoc | 656 | ||||
| -rw-r--r-- | Documentation/technical/long-running-process-protocol.adoc (renamed from Documentation/technical/long-running-process-protocol.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/meson.build | 63 | ||||
| -rw-r--r-- | Documentation/technical/multi-pack-index.adoc (renamed from Documentation/technical/multi-pack-index.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/pack-heuristics.adoc (renamed from Documentation/technical/pack-heuristics.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/packfile-uri.adoc (renamed from Documentation/technical/packfile-uri.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/parallel-checkout.adoc (renamed from Documentation/technical/parallel-checkout.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/partial-clone.adoc (renamed from Documentation/technical/partial-clone.txt) | 2 | ||||
| -rw-r--r-- | Documentation/technical/platform-support.adoc (renamed from Documentation/technical/platform-support.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/racy-git.adoc (renamed from Documentation/technical/racy-git.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/reftable.adoc (renamed from Documentation/technical/reftable.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/remembering-renames.adoc (renamed from Documentation/technical/remembering-renames.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/repository-version.adoc (renamed from Documentation/technical/repository-version.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/rerere.adoc (renamed from Documentation/technical/rerere.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/scalar.adoc (renamed from Documentation/technical/scalar.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/send-pack-pipeline.adoc (renamed from Documentation/technical/send-pack-pipeline.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/shallow.adoc (renamed from Documentation/technical/shallow.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/sparse-checkout.adoc (renamed from Documentation/technical/sparse-checkout.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/sparse-index.adoc (renamed from Documentation/technical/sparse-index.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/trivial-merge.adoc (renamed from Documentation/technical/trivial-merge.txt) | 0 | ||||
| -rw-r--r-- | Documentation/technical/unit-tests.adoc (renamed from Documentation/technical/unit-tests.txt) | 0 | ||||
| -rw-r--r-- | Documentation/trace2-target-values.adoc (renamed from Documentation/trace2-target-values.txt) | 0 | ||||
| -rw-r--r-- | Documentation/transfer-data-leaks.adoc (renamed from Documentation/transfer-data-leaks.txt) | 0 | ||||
| -rw-r--r-- | Documentation/urls-remotes.adoc (renamed from Documentation/urls-remotes.txt) | 2 | ||||
| -rw-r--r-- | Documentation/urls.adoc (renamed from Documentation/urls.txt) | 0 | ||||
| -rw-r--r-- | Documentation/user-manual.adoc (renamed from Documentation/user-manual.txt) | 2 | ||||
| -rw-r--r-- | GIT-BUILD-OPTIONS.in | 4 | ||||
| -rwxr-xr-x | GIT-VERSION-GEN | 52 | ||||
| -rw-r--r-- | Makefile | 118 | ||||
| -rw-r--r-- | README.md | 14 | ||||
| l--------- | RelNotes | 2 | ||||
| -rw-r--r-- | add-interactive.c | 19 | ||||
| -rw-r--r-- | add-patch.c | 2 | ||||
| -rw-r--r-- | advice.h | 2 | ||||
| -rw-r--r-- | apply.c | 5 | ||||
| -rw-r--r-- | archive-tar.c | 4 | ||||
| -rw-r--r-- | archive.c | 1 | ||||
| -rw-r--r-- | bisect.c | 13 | ||||
| -rw-r--r-- | branch.c | 7 | ||||
| -rw-r--r-- | builtin.h | 4 | ||||
| -rw-r--r-- | builtin/am.c | 16 | ||||
| -rw-r--r-- | builtin/backfill.c | 147 | ||||
| -rw-r--r-- | builtin/blame.c | 6 | ||||
| -rw-r--r-- | builtin/branch.c | 7 | ||||
| -rw-r--r-- | builtin/bugreport.c | 15 | ||||
| -rw-r--r-- | builtin/check-mailmap.c | 2 | ||||
| -rw-r--r-- | builtin/check-ref-format.c | 4 | ||||
| -rw-r--r-- | builtin/checkout--worker.c | 6 | ||||
| -rw-r--r-- | builtin/checkout-index.c | 49 | ||||
| -rw-r--r-- | builtin/clone.c | 356 | ||||
| -rw-r--r-- | builtin/commit-graph.c | 1 | ||||
| -rw-r--r-- | builtin/commit-tree.c | 4 | ||||
| -rw-r--r-- | builtin/commit.c | 18 | ||||
| -rw-r--r-- | builtin/config.c | 8 | ||||
| -rw-r--r-- | builtin/credential-cache--daemon.c | 4 | ||||
| -rw-r--r-- | builtin/credential.c | 9 | ||||
| -rw-r--r-- | builtin/diagnose.c | 4 | ||||
| -rw-r--r-- | builtin/diff-files.c | 3 | ||||
| -rw-r--r-- | builtin/diff-index.c | 3 | ||||
| -rw-r--r-- | builtin/diff-pairs.c | 207 | ||||
| -rw-r--r-- | builtin/diff-tree.c | 3 | ||||
| -rw-r--r-- | builtin/difftool.c | 95 | ||||
| -rw-r--r-- | builtin/fast-export.c | 188 | ||||
| -rw-r--r-- | builtin/fast-import.c | 59 | ||||
| -rw-r--r-- | builtin/fetch-pack.c | 2 | ||||
| -rw-r--r-- | builtin/fetch.c | 69 | ||||
| -rw-r--r-- | builtin/for-each-ref.c | 6 | ||||
| -rw-r--r-- | builtin/fsck.c | 55 | ||||
| -rw-r--r-- | builtin/fsmonitor--daemon.c | 4 | ||||
| -rw-r--r-- | builtin/gc.c | 40 | ||||
| -rw-r--r-- | builtin/get-tar-commit-id.c | 4 | ||||
| -rw-r--r-- | builtin/grep.c | 4 | ||||
| -rw-r--r-- | builtin/help.c | 4 | ||||
| -rw-r--r-- | builtin/index-pack.c | 70 | ||||
| -rw-r--r-- | builtin/init-db.c | 8 | ||||
| -rw-r--r-- | builtin/log.c | 63 | ||||
| -rw-r--r-- | builtin/ls-files.c | 36 | ||||
| -rw-r--r-- | builtin/mailinfo.c | 2 | ||||
| -rw-r--r-- | builtin/mailsplit.c | 4 | ||||
| -rw-r--r-- | builtin/merge-base.c | 4 | ||||
| -rw-r--r-- | builtin/merge-index.c | 7 | ||||
| -rw-r--r-- | builtin/merge-ours.c | 3 | ||||
| -rw-r--r-- | builtin/merge-recursive.c | 6 | ||||
| -rw-r--r-- | builtin/merge-tree.c | 11 | ||||
| -rw-r--r-- | builtin/merge.c | 4 | ||||
| -rw-r--r-- | builtin/notes.c | 9 | ||||
| -rw-r--r-- | builtin/pack-objects.c | 214 | ||||
| -rw-r--r-- | builtin/pack-redundant.c | 3 | ||||
| -rw-r--r-- | builtin/pack-refs.c | 8 | ||||
| -rw-r--r-- | builtin/patch-id.c | 14 | ||||
| -rw-r--r-- | builtin/prune.c | 3 | ||||
| -rw-r--r-- | builtin/push.c | 2 | ||||
| -rw-r--r-- | builtin/rebase.c | 8 | ||||
| -rw-r--r-- | builtin/receive-pack.c | 30 | ||||
| -rw-r--r-- | builtin/refs.c | 7 | ||||
| -rw-r--r-- | builtin/remote-ext.c | 2 | ||||
| -rw-r--r-- | builtin/remote-fd.c | 1 | ||||
| -rw-r--r-- | builtin/remote.c | 13 | ||||
| -rw-r--r-- | builtin/repack.c | 16 | ||||
| -rw-r--r-- | builtin/replace.c | 2 | ||||
| -rw-r--r-- | builtin/replay.c | 7 | ||||
| -rw-r--r-- | builtin/rerere.c | 11 | ||||
| -rw-r--r-- | builtin/rev-list.c | 112 | ||||
| -rw-r--r-- | builtin/rev-parse.c | 8 | ||||
| -rw-r--r-- | builtin/send-pack.c | 7 | ||||
| -rw-r--r-- | builtin/show-index.c | 2 | ||||
| -rw-r--r-- | builtin/submodule--helper.c | 4 | ||||
| -rw-r--r-- | builtin/tag.c | 3 | ||||
| -rw-r--r-- | builtin/unpack-file.c | 8 | ||||
| -rw-r--r-- | builtin/unpack-objects.c | 49 | ||||
| -rw-r--r-- | builtin/update-index.c | 4 | ||||
| -rw-r--r-- | builtin/update-ref.c | 15 | ||||
| -rw-r--r-- | builtin/update-server-info.c | 8 | ||||
| -rw-r--r-- | builtin/upload-archive.c | 6 | ||||
| -rw-r--r-- | builtin/upload-pack.c | 6 | ||||
| -rw-r--r-- | builtin/var.c | 3 | ||||
| -rw-r--r-- | builtin/verify-commit.c | 13 | ||||
| -rw-r--r-- | builtin/verify-tag.c | 8 | ||||
| -rw-r--r-- | builtin/worktree.c | 43 | ||||
| -rw-r--r-- | bulk-checkin.c | 28 | ||||
| -rw-r--r-- | bundle.c | 4 | ||||
| -rw-r--r-- | bundle.h | 2 | ||||
| -rwxr-xr-x | ci/install-dependencies.sh | 12 | ||||
| -rwxr-xr-x | ci/lib.sh | 52 | ||||
| -rwxr-xr-x | ci/print-test-failures.sh | 5 | ||||
| -rwxr-xr-x | ci/run-build-and-tests.sh | 8 | ||||
| -rw-r--r-- | combine-diff.c | 80 | ||||
| -rw-r--r-- | command-list.txt | 2 | ||||
| -rw-r--r-- | commit-graph.c | 22 | ||||
| -rw-r--r-- | commit-reach.c | 75 | ||||
| -rw-r--r-- | commit-reach.h | 10 | ||||
| -rw-r--r-- | commit.c | 10 | ||||
| -rw-r--r-- | commit.h | 2 | ||||
| -rw-r--r-- | common-exit.c | 26 | ||||
| -rw-r--r-- | common-init.c | 63 | ||||
| -rw-r--r-- | common-init.h | 6 | ||||
| -rw-r--r-- | common-main.c | 83 | ||||
| -rw-r--r-- | compat/bswap.h | 24 | ||||
| -rw-r--r-- | compat/mingw.c | 4 | ||||
| -rw-r--r-- | compat/precompose_utf8.c | 6 | ||||
| -rw-r--r-- | compat/zlib-compat.h | 53 | ||||
| -rw-r--r-- | compat/zlib-uncompress2.c | 96 | ||||
| -rw-r--r-- | config.c | 26 | ||||
| -rw-r--r-- | config.h | 9 | ||||
| -rw-r--r-- | connect.c | 34 | ||||
| -rw-r--r-- | contrib/buildsystems/CMakeLists.txt | 16 | ||||
| -rw-r--r-- | contrib/coccinelle/meson.build | 89 | ||||
| -rw-r--r-- | contrib/completion/git-completion.bash | 17 | ||||
| -rw-r--r-- | contrib/contacts/Makefile | 2 | ||||
| -rw-r--r-- | contrib/contacts/git-contacts.adoc (renamed from contrib/contacts/git-contacts.txt) | 0 | ||||
| -rw-r--r-- | contrib/contacts/meson.build | 55 | ||||
| -rw-r--r-- | contrib/credential/libsecret/Makefile | 3 | ||||
| -rw-r--r-- | contrib/credential/libsecret/git-credential-libsecret.c | 10 | ||||
| -rw-r--r-- | contrib/credential/libsecret/meson.build | 9 | ||||
| -rw-r--r-- | contrib/credential/meson.build | 3 | ||||
| -rw-r--r-- | contrib/credential/netrc/meson.build | 20 | ||||
| -rwxr-xr-x | contrib/credential/netrc/t-git-credential-netrc.sh | 2 | ||||
| -rwxr-xr-x | contrib/credential/netrc/test.pl | 7 | ||||
| -rw-r--r-- | contrib/credential/osxkeychain/Makefile | 1 | ||||
| -rw-r--r-- | contrib/credential/osxkeychain/git-credential-osxkeychain.c | 2 | ||||
| -rw-r--r-- | contrib/credential/osxkeychain/meson.build | 9 | ||||
| -rw-r--r-- | contrib/credential/wincred/Makefile | 3 | ||||
| -rw-r--r-- | contrib/credential/wincred/git-credential-wincred.c | 2 | ||||
| -rw-r--r-- | contrib/credential/wincred/meson.build | 5 | ||||
| -rw-r--r-- | contrib/diff-highlight/Makefile | 3 | ||||
| -rw-r--r-- | contrib/diff-highlight/t/Makefile | 5 | ||||
| -rw-r--r-- | contrib/libgit-rs/Cargo.lock | 77 | ||||
| -rw-r--r-- | contrib/libgit-rs/Cargo.toml | 17 | ||||
| -rw-r--r-- | contrib/libgit-rs/README.md | 13 | ||||
| -rw-r--r-- | contrib/libgit-rs/build.rs | 4 | ||||
| -rw-r--r-- | contrib/libgit-rs/src/config.rs | 106 | ||||
| -rw-r--r-- | contrib/libgit-rs/src/lib.rs | 1 | ||||
| -rw-r--r-- | contrib/libgit-rs/testdata/config1 | 2 | ||||
| -rw-r--r-- | contrib/libgit-rs/testdata/config2 | 2 | ||||
| -rw-r--r-- | contrib/libgit-rs/testdata/config3 | 2 | ||||
| -rw-r--r-- | contrib/libgit-sys/Cargo.lock | 69 | ||||
| -rw-r--r-- | contrib/libgit-sys/Cargo.toml | 19 | ||||
| -rw-r--r-- | contrib/libgit-sys/README.md | 4 | ||||
| -rw-r--r-- | contrib/libgit-sys/build.rs | 35 | ||||
| -rw-r--r-- | contrib/libgit-sys/public_symbol_export.c | 59 | ||||
| -rw-r--r-- | contrib/libgit-sys/public_symbol_export.h | 18 | ||||
| -rw-r--r-- | contrib/libgit-sys/src/lib.rs | 79 | ||||
| -rwxr-xr-x | contrib/long-running-filter/example.pl | 2 | ||||
| -rw-r--r-- | contrib/meson.build | 7 | ||||
| -rw-r--r-- | contrib/mw-to-git/Makefile | 5 | ||||
| -rw-r--r-- | contrib/mw-to-git/t/Makefile | 3 | ||||
| -rw-r--r-- | contrib/persistent-https/Makefile | 5 | ||||
| -rw-r--r-- | contrib/subtree/.gitignore | 2 | ||||
| -rw-r--r-- | contrib/subtree/Makefile | 25 | ||||
| -rw-r--r-- | contrib/subtree/git-subtree.adoc (renamed from contrib/subtree/git-subtree.txt) | 0 | ||||
| -rw-r--r-- | contrib/subtree/meson.build | 71 | ||||
| -rw-r--r-- | contrib/subtree/t/Makefile | 5 | ||||
| -rwxr-xr-x | contrib/thunderbird-patch-inline/appp.sh | 2 | ||||
| -rw-r--r-- | copy.c | 4 | ||||
| -rw-r--r-- | credential.c | 34 | ||||
| -rw-r--r-- | credential.h | 11 | ||||
| -rw-r--r-- | csum-file.c | 45 | ||||
| -rw-r--r-- | csum-file.h | 6 | ||||
| -rw-r--r-- | date.c | 6 | ||||
| -rw-r--r-- | decorate.c | 15 | ||||
| -rw-r--r-- | delta-islands.c | 3 | ||||
| -rw-r--r-- | diagnose.c | 15 | ||||
| -rw-r--r-- | diagnose.h | 5 | ||||
| -rw-r--r-- | diff-lib.c | 36 | ||||
| -rw-r--r-- | diff.c | 114 | ||||
| -rw-r--r-- | diff.h | 55 | ||||
| -rw-r--r-- | diffcore-rename.c | 10 | ||||
| -rw-r--r-- | diffcore.h | 2 | ||||
| -rw-r--r-- | dir-iterator.c | 24 | ||||
| -rw-r--r-- | dir-iterator.h | 11 | ||||
| -rw-r--r-- | dir.c | 12 | ||||
| -rw-r--r-- | dir.h | 4 | ||||
| -rw-r--r-- | editor.c | 6 | ||||
| -rw-r--r-- | entry.c | 4 | ||||
| -rw-r--r-- | environment.c | 28 | ||||
| -rw-r--r-- | environment.h | 11 | ||||
| -rw-r--r-- | fetch-pack.c | 6 | ||||
| -rw-r--r-- | fsck.c | 2 | ||||
| -rw-r--r-- | fsck.h | 6 | ||||
| -rwxr-xr-x | generate-cmdlist.sh | 2 | ||||
| -rwxr-xr-x | generate-configlist.sh | 2 | ||||
| -rwxr-xr-x | generate-hooklist.sh | 2 | ||||
| -rw-r--r-- | git-compat-util.h | 14 | ||||
| -rw-r--r-- | git-gui/Makefile | 1 | ||||
| -rw-r--r-- | git-gui/po/glossary/Makefile | 3 | ||||
| -rwxr-xr-x | git-instaweb.sh | 4 | ||||
| -rwxr-xr-x | git-submodule.sh | 216 | ||||
| -rw-r--r-- | git-zlib.c | 7 | ||||
| -rw-r--r-- | git-zlib.h | 2 | ||||
| -rw-r--r-- | git.c | 14 | ||||
| -rw-r--r-- | gitk-git/Makefile | 5 | ||||
| -rwxr-xr-x | gitk-git/generate-tcl.sh | 11 | ||||
| -rwxr-xr-x | gitk-git/gitk | 213 | ||||
| -rw-r--r-- | gitk-git/meson.build | 30 | ||||
| -rw-r--r-- | gitk-git/po/meson.build | 19 | ||||
| -rw-r--r-- | graph.c | 3 | ||||
| -rw-r--r-- | hash.h | 94 | ||||
| -rw-r--r-- | help.c | 53 | ||||
| -rw-r--r-- | hook.c | 3 | ||||
| -rw-r--r-- | http-backend.c | 2 | ||||
| -rw-r--r-- | http-push.c | 6 | ||||
| -rw-r--r-- | http.c | 33 | ||||
| -rw-r--r-- | http.h | 2 | ||||
| -rw-r--r-- | ident.c | 2 | ||||
| -rw-r--r-- | imap-send.c | 10 | ||||
| -rw-r--r-- | iterator.h | 2 | ||||
| -rw-r--r-- | list-objects-filter-options.h | 2 | ||||
| -rw-r--r-- | log-tree.c | 2 | ||||
| -rw-r--r-- | loose.c | 8 | ||||
| -rw-r--r-- | mailinfo.c | 5 | ||||
| -rw-r--r-- | mailinfo.h | 4 | ||||
| -rw-r--r-- | match-trees.c | 50 | ||||
| -rw-r--r-- | merge-ort-wrappers.c | 72 | ||||
| -rw-r--r-- | merge-ort-wrappers.h | 12 | ||||
| -rw-r--r-- | merge-ort.c | 56 | ||||
| -rw-r--r-- | merge-ort.h | 5 | ||||
| -rw-r--r-- | merge-recursive.c | 15 | ||||
| -rw-r--r-- | meson.build | 360 | ||||
| -rw-r--r-- | meson_options.txt | 28 | ||||
| -rw-r--r-- | midx-write.c | 17 | ||||
| -rw-r--r-- | midx.c | 13 | ||||
| -rw-r--r-- | notes-merge.c | 26 | ||||
| -rw-r--r-- | object-file.c | 251 | ||||
| -rw-r--r-- | object-name.c | 81 | ||||
| -rw-r--r-- | object-name.h | 6 | ||||
| -rw-r--r-- | oss-fuzz/fuzz-parse-attr-line.c | 2 | ||||
| -rw-r--r-- | oss-fuzz/meson.build | 20 | ||||
| -rw-r--r-- | pack-bitmap-write.c | 8 | ||||
| -rw-r--r-- | pack-bitmap.c | 4 | ||||
| -rw-r--r-- | pack-check.c | 6 | ||||
| -rw-r--r-- | pack-objects.h | 28 | ||||
| -rw-r--r-- | pack-write.c | 106 | ||||
| -rw-r--r-- | pack.h | 33 | ||||
| -rw-r--r-- | packfile.c | 23 | ||||
| -rw-r--r-- | packfile.h | 8 | ||||
| -rw-r--r-- | pager.c | 14 | ||||
| -rw-r--r-- | pager.h | 7 | ||||
| -rw-r--r-- | parse-options.c | 53 | ||||
| -rw-r--r-- | parse-options.h | 15 | ||||
| -rw-r--r-- | path-walk.c | 609 | ||||
| -rw-r--r-- | path-walk.h | 80 | ||||
| -rw-r--r-- | path.c | 166 | ||||
| -rw-r--r-- | path.h | 191 | ||||
| -rw-r--r-- | po/bg.po | 446 | ||||
| -rw-r--r-- | po/de.po | 447 | ||||
| -rw-r--r-- | po/fr.po | 452 | ||||
| -rw-r--r-- | po/id.po | 520 | ||||
| -rw-r--r-- | po/it.po | 2 | ||||
| -rw-r--r-- | po/ko.po | 3 | ||||
| -rw-r--r-- | po/sv.po | 539 | ||||
| -rw-r--r-- | po/tr.po | 436 | ||||
| -rw-r--r-- | po/uk.po | 469 | ||||
| -rw-r--r-- | po/vi.po | 533 | ||||
| -rw-r--r-- | po/zh_CN.po | 540 | ||||
| -rw-r--r-- | po/zh_TW.po | 574 | ||||
| -rw-r--r-- | preload-index.c | 4 | ||||
| -rw-r--r-- | prio-queue.h | 4 | ||||
| -rw-r--r-- | progress.c | 34 | ||||
| -rw-r--r-- | progress.h | 13 | ||||
| -rw-r--r-- | promisor-remote.c | 242 | ||||
| -rw-r--r-- | promisor-remote.h | 37 | ||||
| -rw-r--r-- | prune-packed.c | 3 | ||||
| -rw-r--r-- | pseudo-merge.c | 3 | ||||
| -rw-r--r-- | pseudo-merge.h | 2 | ||||
| -rw-r--r-- | reachable.c | 6 | ||||
| -rw-r--r-- | read-cache.c | 59 | ||||
| -rw-r--r-- | ref-filter.c | 119 | ||||
| -rw-r--r-- | ref-filter.h | 13 | ||||
| -rw-r--r-- | refs.c | 254 | ||||
| -rw-r--r-- | refs.h | 33 | ||||
| -rw-r--r-- | refs/debug.c | 20 | ||||
| -rw-r--r-- | refs/files-backend.c | 130 | ||||
| -rw-r--r-- | refs/iterator.c | 150 | ||||
| -rw-r--r-- | refs/packed-backend.c | 455 | ||||
| -rw-r--r-- | refs/ref-cache.c | 88 | ||||
| -rw-r--r-- | refs/refs-internal.h | 56 | ||||
| -rw-r--r-- | refs/reftable-backend.c | 132 | ||||
| -rw-r--r-- | refspec.c | 235 | ||||
| -rw-r--r-- | refspec.h | 39 | ||||
| -rw-r--r-- | reftable/basics.c | 10 | ||||
| -rw-r--r-- | reftable/basics.h | 4 | ||||
| -rw-r--r-- | reftable/block.c | 21 | ||||
| -rw-r--r-- | reftable/block.h | 14 | ||||
| -rw-r--r-- | reftable/blocksource.c | 8 | ||||
| -rw-r--r-- | reftable/reader.c | 34 | ||||
| -rw-r--r-- | reftable/reader.h | 6 | ||||
| -rw-r--r-- | reftable/record.c | 125 | ||||
| -rw-r--r-- | reftable/record.h | 25 | ||||
| -rw-r--r-- | reftable/reftable-blocksource.h | 13 | ||||
| -rw-r--r-- | reftable/reftable-error.h | 1 | ||||
| -rw-r--r-- | reftable/reftable-record.h | 4 | ||||
| -rw-r--r-- | reftable/reftable-writer.h | 26 | ||||
| -rw-r--r-- | reftable/stack.c | 22 | ||||
| -rw-r--r-- | reftable/system.h | 3 | ||||
| -rw-r--r-- | reftable/writer.c | 22 | ||||
| -rw-r--r-- | remote-curl.c | 4 | ||||
| -rw-r--r-- | remote.c | 274 | ||||
| -rw-r--r-- | remote.h | 24 | ||||
| -rw-r--r-- | repo-settings.c | 44 | ||||
| -rw-r--r-- | repo-settings.h | 14 | ||||
| -rw-r--r-- | repository.c | 6 | ||||
| -rw-r--r-- | rerere.c | 119 | ||||
| -rw-r--r-- | rerere.h | 3 | ||||
| -rw-r--r-- | resolve-undo.c | 14 | ||||
| -rw-r--r-- | resolve-undo.h | 6 | ||||
| -rw-r--r-- | revision.c | 7 | ||||
| -rw-r--r-- | scalar.c | 4 | ||||
| -rw-r--r-- | send-pack.c | 87 | ||||
| -rw-r--r-- | send-pack.h | 16 | ||||
| -rw-r--r-- | sequencer.c | 12 | ||||
| -rw-r--r-- | serve.c | 62 | ||||
| -rw-r--r-- | serve.h | 6 | ||||
| -rw-r--r-- | server-info.c | 42 | ||||
| -rw-r--r-- | server-info.h | 4 | ||||
| -rw-r--r-- | setup.c | 80 | ||||
| -rw-r--r-- | shallow.c | 44 | ||||
| -rw-r--r-- | shallow.h | 6 | ||||
| -rw-r--r-- | simple-ipc.h | 2 | ||||
| -rw-r--r-- | submodule.c | 15 | ||||
| -rw-r--r-- | submodule.h | 3 | ||||
| -rw-r--r-- | t/Makefile | 15 | ||||
| -rw-r--r-- | t/README | 4 | ||||
| -rwxr-xr-x | t/aggregate-results.sh | 2 | ||||
| -rw-r--r-- | t/helper/meson.build | 6 | ||||
| -rw-r--r-- | t/helper/test-csprng.c | 2 | ||||
| -rw-r--r-- | t/helper/test-dir-iterator.c | 1 | ||||
| -rw-r--r-- | t/helper/test-hash-speed.c | 8 | ||||
| -rw-r--r-- | t/helper/test-hash.c | 10 | ||||
| -rw-r--r-- | t/helper/test-name-hash.c | 23 | ||||
| -rw-r--r-- | t/helper/test-path-walk.c | 132 | ||||
| -rw-r--r-- | t/helper/test-progress.c | 6 | ||||
| -rw-r--r-- | t/helper/test-reach.c | 6 | ||||
| -rw-r--r-- | t/helper/test-ref-store.c | 7 | ||||
| -rw-r--r-- | t/helper/test-rot13-filter.c | 2 | ||||
| -rw-r--r-- | t/helper/test-serve-v2.c | 7 | ||||
| -rw-r--r-- | t/helper/test-sha1.c | 7 | ||||
| -rwxr-xr-x | t/helper/test-sha1.sh | 38 | ||||
| -rw-r--r-- | t/helper/test-sha256.c | 2 | ||||
| -rw-r--r-- | t/helper/test-simple-ipc.c | 4 | ||||
| -rw-r--r-- | t/helper/test-tool.c | 3 | ||||
| -rw-r--r-- | t/helper/test-tool.h | 5 | ||||
| -rw-r--r-- | t/interop/Makefile | 5 | ||||
| -rw-r--r-- | t/lib-credential.sh | 15 | ||||
| -rw-r--r-- | t/lib-gettext.sh | 2 | ||||
| -rw-r--r-- | t/meson.build | 33 | ||||
| -rw-r--r-- | t/perf/Makefile | 5 | ||||
| -rwxr-xr-x | t/perf/p5313-pack-objects.sh | 70 | ||||
| -rwxr-xr-x | t/perf/p5314-name-hash.sh | 31 | ||||
| -rwxr-xr-x | t/t0001-init.sh | 30 | ||||
| -rwxr-xr-x | t/t0012-help.sh | 3 | ||||
| -rwxr-xr-x | t/t0060-path-utils.sh | 10 | ||||
| -rwxr-xr-x | t/t0091-bugreport.sh | 3 | ||||
| -rwxr-xr-x | t/t0210-trace2-normal.sh | 9 | ||||
| -rwxr-xr-x | t/t0450-txt-doc-vs-help.sh | 50 | ||||
| -rw-r--r-- | t/t0450/adoc-help-mismatches (renamed from t/t0450/txt-help-mismatches) | 1 | ||||
| -rwxr-xr-x | t/t0602-reffiles-fsck.sh | 1209 | ||||
| -rwxr-xr-x | t/t0610-reftable-basics.sh | 7 | ||||
| -rwxr-xr-x | t/t1006-cat-file.sh | 31 | ||||
| -rwxr-xr-x | t/t1400-update-ref.sh | 9 | ||||
| -rwxr-xr-x | t/t1419-exclude-refs.sh | 26 | ||||
| -rwxr-xr-x | t/t1460-refs-migrate.sh | 57 | ||||
| -rwxr-xr-x | t/t2006-checkout-index-basic.sh | 7 | ||||
| -rwxr-xr-x | t/t3004-ls-files-basic.sh | 7 | ||||
| -rwxr-xr-x | t/t3200-branch.sh | 14 | ||||
| -rwxr-xr-x | t/t3203-branch-output.sh | 28 | ||||
| -rwxr-xr-x | t/t3404-rebase-interactive.sh | 14 | ||||
| -rwxr-xr-x | t/t3430-rebase-merges.sh | 20 | ||||
| -rwxr-xr-x | t/t3650-replay-basics.sh | 22 | ||||
| -rwxr-xr-x | t/t4070-diff-pairs.sh | 90 | ||||
| -rwxr-xr-x | t/t4100-apply-stat.sh | 13 | ||||
| -rwxr-xr-x | t/t4151-am-abort.sh | 2 | ||||
| -rwxr-xr-x | t/t4203-mailmap.sh | 12 | ||||
| -rwxr-xr-x | t/t4206-log-follow-harder-copies.sh | 32 | ||||
| -rwxr-xr-x | t/t4209-log-pickaxe.sh | 16 | ||||
| -rwxr-xr-x | t/t4255-am-submodule.sh | 1 | ||||
| -rwxr-xr-x | t/t4301-merge-tree-write-tree.sh | 6 | ||||
| -rwxr-xr-x | t/t5300-pack-object.sh | 34 | ||||
| -rwxr-xr-x | t/t5310-pack-bitmaps.sh | 35 | ||||
| -rwxr-xr-x | t/t5323-pack-redundant.sh | 6 | ||||
| -rwxr-xr-x | t/t5333-pseudo-merge-bitmaps.sh | 3 | ||||
| -rwxr-xr-x | t/t5400-send-pack.sh | 7 | ||||
| -rwxr-xr-x | t/t5401-update-hooks.sh | 16 | ||||
| -rwxr-xr-x | t/t5503-tagfollow.sh | 14 | ||||
| -rwxr-xr-x | t/t5504-fetch-receive-strict.sh | 45 | ||||
| -rwxr-xr-x | t/t5505-remote.sh | 16 | ||||
| -rwxr-xr-x | t/t5510-fetch.sh | 37 | ||||
| -rwxr-xr-x | t/t5515-fetch-merge-logic.sh | 47 | ||||
| -rwxr-xr-x | t/t5516-fetch-push.sh | 26 | ||||
| -rwxr-xr-x | t/t5540-http-push-webdav.sh | 10 | ||||
| -rwxr-xr-x | t/t5543-atomic-push.sh | 30 | ||||
| -rwxr-xr-x | t/t5548-push-porcelain.sh | 443 | ||||
| -rwxr-xr-x | t/t5620-backfill.sh | 211 | ||||
| -rwxr-xr-x | t/t5621-clone-revision.sh | 122 | ||||
| -rwxr-xr-x | t/t5701-git-serve.sh | 26 | ||||
| -rwxr-xr-x | t/t5702-protocol-v2.sh | 44 | ||||
| -rwxr-xr-x | t/t5710-promisor-remote-capability.sh | 312 | ||||
| -rwxr-xr-x | t/t6012-rev-list-simplify.sh | 2 | ||||
| -rwxr-xr-x | t/t6020-bundle-misc.sh | 6 | ||||
| -rwxr-xr-x | t/t6022-rev-list-missing.sh | 53 | ||||
| -rwxr-xr-x | t/t6120-describe.sh | 24 | ||||
| -rwxr-xr-x | t/t6300-for-each-ref.sh | 7 | ||||
| -rwxr-xr-x | t/t6423-merge-rename-directories.sh | 50 | ||||
| -rwxr-xr-x | t/t6427-diff3-conflict-markers.sh | 2 | ||||
| -rwxr-xr-x | t/t6434-merge-recursive-rename-options.sh | 2 | ||||
| -rwxr-xr-x | t/t6500-gc.sh | 33 | ||||
| -rwxr-xr-x | t/t6600-test-reach.sh | 29 | ||||
| -rwxr-xr-x | t/t6601-path-walk.sh | 400 | ||||
| -rwxr-xr-x | t/t7030-verify-tag.sh | 7 | ||||
| -rwxr-xr-x | t/t7110-reset-merge.sh | 12 | ||||
| -rwxr-xr-x | t/t7406-submodule-update.sh | 4 | ||||
| -rwxr-xr-x | t/t7407-submodule-foreach.sh | 4 | ||||
| -rwxr-xr-x | t/t7422-submodule-output.sh | 43 | ||||
| -rwxr-xr-x | t/t7510-signed-commit.sh | 7 | ||||
| -rwxr-xr-x | t/t7600-merge.sh | 2 | ||||
| -rwxr-xr-x | t/t7603-merge-reduce-heads.sh | 24 | ||||
| -rwxr-xr-x | t/t7609-mergetool--lib.sh | 2 | ||||
| -rwxr-xr-x | t/t7700-repack.sh | 16 | ||||
| -rwxr-xr-x | t/t7701-repack-unpack-unreachable.sh | 16 | ||||
| -rwxr-xr-x | t/t7704-repack-cruft.sh | 66 | ||||
| -rwxr-xr-x | t/t8002-blame.sh | 4 | ||||
| -rwxr-xr-x | t/t9003-help-autocorrect.sh | 17 | ||||
| -rwxr-xr-x | t/t9350-fast-export.sh | 116 | ||||
| -rw-r--r-- | t/test-lib-functions.sh | 46 | ||||
| -rw-r--r-- | t/test-lib.sh | 24 | ||||
| -rwxr-xr-x | t/unit-tests/generate-clar-decls.sh | 1 | ||||
| -rw-r--r-- | t/unit-tests/lib-oid.c | 32 | ||||
| -rw-r--r-- | t/unit-tests/lib-oid.h | 9 | ||||
| -rw-r--r-- | t/unit-tests/t-example-decorate.c | 74 | ||||
| -rw-r--r-- | t/unit-tests/t-mem-pool.c | 31 | ||||
| -rw-r--r-- | t/unit-tests/t-oid-array.c | 126 | ||||
| -rw-r--r-- | t/unit-tests/t-oidmap.c | 181 | ||||
| -rw-r--r-- | t/unit-tests/t-oidtree.c | 122 | ||||
| -rw-r--r-- | t/unit-tests/t-prio-queue.c | 91 | ||||
| -rw-r--r-- | t/unit-tests/t-reftable-basics.c | 2 | ||||
| -rw-r--r-- | t/unit-tests/t-reftable-readwrite.c | 8 | ||||
| -rw-r--r-- | t/unit-tests/t-reftable-record.c | 19 | ||||
| -rw-r--r-- | t/unit-tests/t-reftable-stack.c | 54 | ||||
| -rw-r--r-- | t/unit-tests/t-strbuf.c | 122 | ||||
| -rw-r--r-- | t/unit-tests/t-strcmp-offset.c | 35 | ||||
| -rw-r--r-- | t/unit-tests/u-example-decorate.c | 64 | ||||
| -rw-r--r-- | t/unit-tests/u-hash.c (renamed from t/unit-tests/t-hash.c) | 77 | ||||
| -rw-r--r-- | t/unit-tests/u-hashmap.c (renamed from t/unit-tests/t-hashmap.c) | 226 | ||||
| -rw-r--r-- | t/unit-tests/u-mem-pool.c | 25 | ||||
| -rw-r--r-- | t/unit-tests/u-oid-array.c | 129 | ||||
| -rw-r--r-- | t/unit-tests/u-oidmap.c | 136 | ||||
| -rw-r--r-- | t/unit-tests/u-oidtree.c | 107 | ||||
| -rw-r--r-- | t/unit-tests/u-prio-queue.c | 94 | ||||
| -rw-r--r-- | t/unit-tests/u-reftable-tree.c (renamed from t/unit-tests/t-reftable-tree.c) | 30 | ||||
| -rw-r--r-- | t/unit-tests/u-strbuf.c | 119 | ||||
| -rw-r--r-- | t/unit-tests/u-strcmp-offset.c | 45 | ||||
| -rw-r--r-- | t/unit-tests/unit-test.c | 2 | ||||
| -rw-r--r-- | tempfile.c | 4 | ||||
| -rw-r--r-- | templates/Makefile | 5 | ||||
| -rw-r--r-- | tmp-objdir.c | 32 | ||||
| -rw-r--r-- | tmp-objdir.h | 5 | ||||
| -rw-r--r-- | trace.c | 9 | ||||
| -rw-r--r-- | trace.h | 4 | ||||
| -rw-r--r-- | trace2.c | 2 | ||||
| -rw-r--r-- | trace2.h | 2 | ||||
| -rw-r--r-- | trace2/tr2_sid.c | 6 | ||||
| -rw-r--r-- | trace2/tr2_sysenv.c | 2 | ||||
| -rw-r--r-- | trace2/tr2_tgt_event.c | 3 | ||||
| -rw-r--r-- | trace2/tr2_tgt_normal.c | 5 | ||||
| -rw-r--r-- | trace2/tr2_tgt_perf.c | 5 | ||||
| -rw-r--r-- | transport.c | 20 | ||||
| -rw-r--r-- | transport.h | 2 | ||||
| -rw-r--r-- | tree-diff.c | 152 | ||||
| -rw-r--r-- | unix-socket.c | 4 | ||||
| -rw-r--r-- | unpack-trees.c | 6 | ||||
| -rw-r--r-- | upload-pack.c | 3 | ||||
| -rw-r--r-- | usage.c | 27 | ||||
| -rw-r--r-- | version.c | 76 | ||||
| -rw-r--r-- | version.h | 10 | ||||
| -rw-r--r-- | walker.c | 3 | ||||
| -rw-r--r-- | worktree.c | 95 | ||||
| -rw-r--r-- | worktree.h | 10 | ||||
| -rw-r--r-- | wrapper.c | 24 | ||||
| -rw-r--r-- | wrapper.h | 16 | ||||
| -rw-r--r-- | wt-status.c | 42 | ||||
| -rw-r--r-- | xdiff/xdiff.h | 2 | ||||
| -rw-r--r-- | xdiff/xdiffi.c | 3 | ||||
| -rw-r--r-- | xdiff/xemit.c | 2 | ||||
| -rw-r--r-- | xdiff/xhistogram.c | 8 | ||||
| -rw-r--r-- | xdiff/xinclude.h | 2 | ||||
| -rw-r--r-- | xdiff/xpatience.c | 5 | ||||
| -rw-r--r-- | xdiff/xutils.c | 4 |
1434 files changed, 19384 insertions, 8335 deletions
diff --git a/.editorconfig b/.editorconfig index 15d6cbeab1..2d3929b591 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,7 +4,7 @@ insert_final_newline = true # The settings for C (*.c and *.h) files are mirrored in .clang-format. Keep # them in sync. -[{*.{c,h,sh,perl,pl,pm,txt},config.mak.*,Makefile}] +[{*.{c,h,sh,bash,perl,pl,pm,txt,adoc},config.mak.*,Makefile}] indent_style = tab tab_width = 8 diff --git a/.gitattributes b/.gitattributes index 158c3d45c4..c6a0b35116 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,12 +7,12 @@ *.py text eol=lf diff=python *.bat text eol=crlf CODE_OF_CONDUCT.md -whitespace -/Documentation/**/*.txt text eol=lf +/Documentation/**/*.adoc text eol=lf /command-list.txt text eol=lf /GIT-VERSION-GEN text eol=lf /mergetools/* text eol=lf /t/oid-info/* text eol=lf -/Documentation/git-merge.txt conflict-marker-size=32 -/Documentation/gitk.txt conflict-marker-size=32 -/Documentation/user-manual.txt conflict-marker-size=32 +/Documentation/git-merge.adoc conflict-marker-size=32 +/Documentation/gitk.adoc conflict-marker-size=32 +/Documentation/user-manual.adoc conflict-marker-size=32 /t/t????-*.sh conflict-marker-size=32 diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index 48341e81f4..124301dbbe 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -45,7 +45,7 @@ jobs: - run: ci/install-dependencies.sh if: contains(matrix.os, 'ubuntu') || contains(matrix.os, 'macos') env: - distro: ${{ matrix.os }} + CI_JOB_IMAGE: ${{ matrix.os }} # The Coverity site says the tool is usually updated twice yearly, so the # MD5 of download can be used to determine whether there's been an update. diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 900be9957a..9959b61ece 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -248,6 +248,58 @@ jobs: with: name: failed-tests-windows-vs-${{ matrix.nr }} path: ${{env.FAILED_TEST_ARTIFACTS}} + + windows-meson-build: + name: win+Meson build + needs: ci-config + if: needs.ci-config.outputs.enabled == 'yes' + runs-on: windows-latest + concurrency: + group: windows-meson-build-${{ github.ref }} + cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - name: Set up dependencies + shell: pwsh + run: pip install meson ninja + - name: Setup + shell: pwsh + run: meson setup build -Dperl=disabled -Dcredential_helpers=wincred + - name: Compile + shell: pwsh + run: meson compile -C build + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: windows-meson-artifacts + path: build + windows-meson-test: + name: win+Meson test + runs-on: windows-latest + needs: [ci-config, windows-meson-build] + strategy: + fail-fast: false + matrix: + nr: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + concurrency: + group: windows-meson-test-${{ matrix.nr }}-${{ github.ref }} + cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - name: Set up dependencies + shell: pwsh + run: pip install meson ninja + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: windows-meson-artifacts + path: build + - name: Test + shell: pwsh + run: meson test -C build --list | Select-Object -Skip 1 | Select-String .* | Group-Object -Property { $_.LineNumber % 10 } | Where-Object Name -EQ ${{ matrix.nr }} | ForEach-Object { meson test -C build --no-rebuild --print-errorlogs $_.Group } + regular: name: ${{matrix.vector.jobname}} (${{matrix.vector.pool}}) needs: ci-config @@ -259,20 +311,6 @@ jobs: fail-fast: false matrix: vector: - - jobname: linux-sha256 - cc: clang - pool: ubuntu-latest - - jobname: linux-reftable - cc: clang - pool: ubuntu-latest - - jobname: linux-gcc - cc: gcc - cc_package: gcc-8 - pool: ubuntu-20.04 - - jobname: linux-TEST-vars - cc: gcc - cc_package: gcc-8 - pool: ubuntu-20.04 - jobname: osx-clang cc: clang pool: macos-13 @@ -285,26 +323,11 @@ jobs: - jobname: osx-meson cc: clang pool: macos-13 - - jobname: linux-gcc-default - cc: gcc - pool: ubuntu-latest - - jobname: linux-leaks - cc: gcc - pool: ubuntu-latest - - jobname: linux-reftable-leaks - cc: gcc - pool: ubuntu-latest - - jobname: linux-asan-ubsan - cc: clang - pool: ubuntu-latest - - jobname: linux-meson - cc: gcc - pool: ubuntu-latest env: CC: ${{matrix.vector.cc}} CC_PACKAGE: ${{matrix.vector.cc_package}} jobname: ${{matrix.vector.jobname}} - distro: ${{matrix.vector.pool}} + CI_JOB_IMAGE: ${{matrix.vector.pool}} TEST_OUTPUT_DIRECTORY: ${{github.workspace}}/t runs-on: ${{matrix.vector.pool}} steps: @@ -342,27 +365,48 @@ jobs: fail-fast: false matrix: vector: - - jobname: linux-musl - image: alpine - distro: alpine-latest + - jobname: linux-sha256 + image: ubuntu:rolling + cc: clang + - jobname: linux-reftable + image: ubuntu:rolling + cc: clang + - jobname: linux-TEST-vars + image: ubuntu:20.04 + cc: gcc + cc_package: gcc-8 + - jobname: linux-breaking-changes + cc: gcc + image: ubuntu:rolling + - jobname: linux-leaks + image: ubuntu:rolling + cc: gcc + - jobname: linux-reftable-leaks + image: ubuntu:rolling + cc: gcc + - jobname: linux-asan-ubsan + image: ubuntu:rolling + cc: clang + - jobname: linux-meson + image: ubuntu:rolling + cc: gcc + - jobname: linux-musl-meson + image: alpine:latest # Supported until 2025-04-02. - jobname: linux32 image: i386/ubuntu:focal - distro: ubuntu32-20.04 - jobname: pedantic - image: fedora - distro: fedora-latest + image: fedora:latest # A RHEL 8 compatible distro. Supported until 2029-05-31. - jobname: almalinux-8 image: almalinux:8 - distro: almalinux-8 # Supported until 2026-08-31. - jobname: debian-11 image: debian:11 - distro: debian-11 env: jobname: ${{matrix.vector.jobname}} - distro: ${{matrix.vector.distro}} + CC: ${{matrix.vector.cc}} + CI_JOB_IMAGE: ${{matrix.vector.image}} runs-on: ubuntu-latest container: ${{matrix.vector.image}} steps: @@ -371,10 +415,12 @@ jobs: run: apt -q update && apt -q -y install libc6-amd64 lib64stdc++6 - uses: actions/checkout@v4 - run: ci/install-dependencies.sh - - run: ci/run-build-and-tests.sh + - run: useradd builder --create-home + - run: chown -R builder . + - run: sudo --preserve-env --set-home --user=builder ci/run-build-and-tests.sh - name: print test failures if: failure() && env.FAILED_TEST_ARTIFACTS != '' - run: ci/print-test-failures.sh + run: sudo --preserve-env --set-home --user=builder ci/print-test-failures.sh - name: Upload failed tests' directories if: failure() && env.FAILED_TEST_ARTIFACTS != '' uses: actions/upload-artifact@v4 diff --git a/.gitignore b/.gitignore index e82aa19df0..04c444404e 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ /git-apply /git-archimport /git-archive +/git-backfill /git-bisect /git-blame /git-branch @@ -54,6 +55,7 @@ /git-diff /git-diff-files /git-diff-index +/git-diff-pairs /git-diff-tree /git-difftool /git-difftool--helper @@ -250,3 +252,5 @@ Release/ /git.VC.db *.dSYM /contrib/buildsystems/out +/contrib/libgit-rs/target +/contrib/libgit-sys/target diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9254e01583..2805cdeecb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -36,41 +36,36 @@ test:linux: fi parallel: matrix: - - jobname: linux-old - image: ubuntu:20.04 - CC: gcc - jobname: linux-sha256 - image: ubuntu:latest + image: ubuntu:rolling CC: clang - jobname: linux-reftable - image: ubuntu:latest + image: ubuntu:rolling CC: clang - - jobname: linux-gcc + - jobname: linux-breaking-changes image: ubuntu:20.04 CC: gcc - CC_PACKAGE: gcc-8 - jobname: linux-TEST-vars image: ubuntu:20.04 CC: gcc CC_PACKAGE: gcc-8 - - jobname: linux-gcc-default - image: ubuntu:latest - CC: gcc - jobname: linux-leaks - image: ubuntu:latest + image: ubuntu:rolling CC: gcc - jobname: linux-reftable-leaks - image: ubuntu:latest + image: ubuntu:rolling CC: gcc - jobname: linux-asan-ubsan - image: ubuntu:latest + image: ubuntu:rolling CC: clang - jobname: pedantic image: fedora:latest - - jobname: linux-musl + - jobname: linux-musl-meson image: alpine:latest + - jobname: linux32 + image: i386/ubuntu:20.04 - jobname: linux-meson - image: ubuntu:latest + image: ubuntu:rolling CC: gcc artifacts: paths: @@ -149,6 +144,44 @@ test:mingw64: - git-sdk/usr/bin/bash.exe -l -c 'ci/print-test-failures.sh' parallel: 10 +.msvc-meson: + tags: + - saas-windows-medium-amd64 + before_script: + - choco install -y git meson ninja openssl + - Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1 + - refreshenv + # The certificate store for Python on Windows is broken and fails to fetch + # certificates, see https://bugs.python.org/issue36011. This seems to + # mostly be an issue with how the GitLab image is set up as it is a + # non-issue on GitHub Actions. Work around the issue by importing + # cetrificates manually. + - Invoke-WebRequest https://curl.haxx.se/ca/cacert.pem -OutFile cacert.pem + - openssl pkcs12 -export -nokeys -in cacert.pem -out certs.pfx -passout "pass:" + - Import-PfxCertificate -CertStoreLocation Cert:\LocalMachine\Root -FilePath certs.pfx + +build:msvc-meson: + extends: .msvc-meson + stage: build + script: + - meson setup build -Dperl=disabled -Dbackend_max_links=1 -Dcredential_helpers=wincred + - meson compile -C build + artifacts: + paths: + - build + +test:msvc-meson: + extends: .msvc-meson + stage: test + when: manual + timeout: 6h + needs: + - job: "build:msvc-meson" + artifacts: true + script: + - meson test -C build --list | Select-Object -Skip 1 | Select-String .* | Group-Object -Property { $_.LineNumber % $Env:CI_NODE_TOTAL + 1 } | Where-Object Name -EQ $Env:CI_NODE_INDEX | ForEach-Object { meson test -C build --no-rebuild --print-errorlogs $_.Group; if (!$?) { exit $LASTEXITCODE } } + parallel: 10 + test:fuzz-smoke-tests: image: ubuntu:latest stage: test @@ -183,7 +216,7 @@ check-whitespace: # be defined in all pipelines. script: - | - R=${CI_MERGE_REQUEST_TARGET_BRANCH_SHA-${CI_MERGE_REQUEST_DIFF_BASE_SHA:?}} || exit + R=${CI_MERGE_REQUEST_TARGET_BRANCH_SHA:-${CI_MERGE_REQUEST_DIFF_BASE_SHA:?}} || exit ./ci/check-whitespace.sh "$R" rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' @@ -203,7 +236,7 @@ check-style: # be defined in all pipelines. script: - | - R=${CI_MERGE_REQUEST_TARGET_BRANCH_SHA-${CI_MERGE_REQUEST_DIFF_BASE_SHA:?}} || exit + R=${CI_MERGE_REQUEST_TARGET_BRANCH_SHA:-${CI_MERGE_REQUEST_DIFF_BASE_SHA:?}} || exit ./ci/run-style-check.sh "$R" rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' diff --git a/Documentation/.gitattributes b/Documentation/.gitattributes deleted file mode 100644 index ddb030137d..0000000000 --- a/Documentation/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.txt whitespace diff --git a/Documentation/.gitignore b/Documentation/.gitignore index 9f4bb3c4bf..dd54cc768a 100644 --- a/Documentation/.gitignore +++ b/Documentation/.gitignore @@ -6,11 +6,11 @@ *.pdf git.info gitman.info -howto-index.txt +howto-index.adoc doc.dep -cmds-*.txt -mergetools-*.txt -SubmittingPatches.txt +cmds-*.adoc +mergetools-*.adoc +SubmittingPatches.adoc tmp-doc-diff/ tmp-meson-diff/ GIT-ASCIIDOCFLAGS diff --git a/Documentation/BreakingChanges.txt b/Documentation/BreakingChanges.adoc index 27acff86db..bdfad29d8a 100644 --- a/Documentation/BreakingChanges.txt +++ b/Documentation/BreakingChanges.adoc @@ -66,22 +66,21 @@ changes are made at a certain version boundary, and recording these decisions in this document, are necessary but not sufficient. Because such changes are expected to be numerous, and the design and implementation of them are expected to span over time, they have to -be deployable trivially at such a version boundary. +be deployable trivially at such a version boundary, prepared over long +time. The breaking changes MUST be guarded with the a compile-time switch, WITH_BREAKING_CHANGES, to help this process. When built with it, the resulting Git binary together with its documentation would behave as if these breaking changes slated for the next big version -boundary are already in effect. We may also want to have a CI job -or two to exercise the work-in-progress version of Git with these -breaking changes. +boundary are already in effect. We also have a CI job to exercise +the work-in-progress version of Git with these breaking changes. == Git 3.0 The following subsections document upcoming breaking changes for Git 3.0. There -is no planned release date for this breaking version yet. The early -adopter configuration used for changes for this release is `feature.git3`. +is no planned release date for this breaking version yet. Proposed changes and removals only include items which are "ready" to be done. In other words, this is not supposed to be a wishlist of features that should @@ -154,6 +153,31 @@ Cf. <xmqq1rjuz6n3.fsf_-_@gitster.c.googlers.com>, <CAKvOHKAFXQwt4D8yUCCkf_TQL79mYaJ=KAKhtpDNTvHJFuX1NA@mail.gmail.com>, <20230323204047.GA9290@coredump.intra.peff.net>, +* Support for storing shorthands for remote URLs in "$GIT_COMMON_DIR/branches/" + and "$GIT_COMMON_DIR/remotes/" has been long superseded by storing remotes in + the repository configuration. ++ +The mechanism has originally been introduced in f170e4b39d ([PATCH] fetch/pull: +short-hand notation for remote repositories., 2005-07-16) and was superseded by +6687f8fea2 ([PATCH] Use .git/remote/origin, not .git/branches/origin., +2005-08-20), where we switched from ".git/branches/" to ".git/remotes/". That +commit already mentions an upcoming deprecation of the ".git/branches/" +directory, and starting with a1d4aa7424 (Add repository-layout document., +2005-09-01) we have also marked this layout as deprecated. Eventually we also +started to migrate away from ".git/remotes/" in favor of config-based remotes, +and we have marked the directory as legacy in 3d3d282146 (Documentation: +Grammar correction, wording fixes and cleanup, 2011-08-23) ++ +As our documentation mentions, these directories are unlikely to be used in +modern repositories and most users aren't even aware of these mechanisms. They +have been deprecated for almost 20 years and 14 years respectively, and we are +not aware of any active users that have complained about this deprecation. +Furthermore, the ".git/branches/" directory is nowadays misleadingly named and +may cause confusion as "branches" are almost exclusively used in the context of +references. ++ +These features will be removed. + == Superseded features that will not be deprecated Some features have gained newer replacements that aim to improve the design in diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines index ba047ed224..a0e7041c54 100644 --- a/Documentation/CodingGuidelines +++ b/Documentation/CodingGuidelines @@ -44,7 +44,7 @@ code are expected to match the style the surrounding code already uses (even if it doesn't match the overall style of existing code). But if you must have a list of rules, here are some language -specific ones. Note that Documentation/ToolsForGit.txt document +specific ones. Note that Documentation/ToolsForGit.adoc document has a collection of tips to help you use some external tools to conform to these guidelines. @@ -755,7 +755,7 @@ Externally Visible Names Writing Documentation: Most (if not all) of the documentation pages are written in the - AsciiDoc format in *.txt files (e.g. Documentation/git.txt), and + AsciiDoc format in *.adoc files (e.g. Documentation/git.adoc), and processed into HTML and manpages (e.g. git.html and git.1 in the same directory). diff --git a/Documentation/DecisionMaking.txt b/Documentation/DecisionMaking.adoc index b43c472ae5..b43c472ae5 100644 --- a/Documentation/DecisionMaking.txt +++ b/Documentation/DecisionMaking.adoc diff --git a/Documentation/Makefile b/Documentation/Makefile index aedfe99d1d..e6b20c021f 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -1,3 +1,6 @@ +# The default target of this Makefile is... +all:: + # Import tree-wide shared Makefile behavior and libraries include ../shared.mak @@ -17,56 +20,56 @@ OBSOLETE_HTML = -include GIT-EXCLUDED-PROGRAMS MAN1_TXT += $(filter-out \ - $(patsubst %,%.txt,$(EXCLUDED_PROGRAMS)) \ - $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \ - $(wildcard git-*.txt)) -MAN1_TXT += git.txt -MAN1_TXT += gitk.txt -MAN1_TXT += gitweb.txt -MAN1_TXT += scalar.txt + $(patsubst %,%.adoc,$(EXCLUDED_PROGRAMS)) \ + $(addsuffix .adoc, $(ARTICLES) $(SP_ARTICLES)), \ + $(wildcard git-*.adoc)) +MAN1_TXT += git.adoc +MAN1_TXT += gitk.adoc +MAN1_TXT += gitweb.adoc +MAN1_TXT += scalar.adoc # man5 / man7 guides (note: new guides should also be added to command-list.txt) -MAN5_TXT += gitattributes.txt -MAN5_TXT += gitformat-bundle.txt -MAN5_TXT += gitformat-chunk.txt -MAN5_TXT += gitformat-commit-graph.txt -MAN5_TXT += gitformat-index.txt -MAN5_TXT += gitformat-pack.txt -MAN5_TXT += gitformat-signature.txt -MAN5_TXT += githooks.txt -MAN5_TXT += gitignore.txt -MAN5_TXT += gitmailmap.txt -MAN5_TXT += gitmodules.txt -MAN5_TXT += gitprotocol-capabilities.txt -MAN5_TXT += gitprotocol-common.txt -MAN5_TXT += gitprotocol-http.txt -MAN5_TXT += gitprotocol-pack.txt -MAN5_TXT += gitprotocol-v2.txt -MAN5_TXT += gitrepository-layout.txt -MAN5_TXT += gitweb.conf.txt - -MAN7_TXT += gitcli.txt -MAN7_TXT += gitcore-tutorial.txt -MAN7_TXT += gitcredentials.txt -MAN7_TXT += gitcvs-migration.txt -MAN7_TXT += gitdiffcore.txt -MAN7_TXT += giteveryday.txt -MAN7_TXT += gitfaq.txt -MAN7_TXT += gitglossary.txt -MAN7_TXT += gitpacking.txt -MAN7_TXT += gitnamespaces.txt -MAN7_TXT += gitremote-helpers.txt -MAN7_TXT += gitrevisions.txt -MAN7_TXT += gitsubmodules.txt -MAN7_TXT += gittutorial-2.txt -MAN7_TXT += gittutorial.txt -MAN7_TXT += gitworkflows.txt - -HOWTO_TXT += $(wildcard howto/*.txt) - -DOC_DEP_TXT += $(wildcard *.txt) -DOC_DEP_TXT += $(wildcard config/*.txt) -DOC_DEP_TXT += $(wildcard includes/*.txt) +MAN5_TXT += gitattributes.adoc +MAN5_TXT += gitformat-bundle.adoc +MAN5_TXT += gitformat-chunk.adoc +MAN5_TXT += gitformat-commit-graph.adoc +MAN5_TXT += gitformat-index.adoc +MAN5_TXT += gitformat-pack.adoc +MAN5_TXT += gitformat-signature.adoc +MAN5_TXT += githooks.adoc +MAN5_TXT += gitignore.adoc +MAN5_TXT += gitmailmap.adoc +MAN5_TXT += gitmodules.adoc +MAN5_TXT += gitprotocol-capabilities.adoc +MAN5_TXT += gitprotocol-common.adoc +MAN5_TXT += gitprotocol-http.adoc +MAN5_TXT += gitprotocol-pack.adoc +MAN5_TXT += gitprotocol-v2.adoc +MAN5_TXT += gitrepository-layout.adoc +MAN5_TXT += gitweb.conf.adoc + +MAN7_TXT += gitcli.adoc +MAN7_TXT += gitcore-tutorial.adoc +MAN7_TXT += gitcredentials.adoc +MAN7_TXT += gitcvs-migration.adoc +MAN7_TXT += gitdiffcore.adoc +MAN7_TXT += giteveryday.adoc +MAN7_TXT += gitfaq.adoc +MAN7_TXT += gitglossary.adoc +MAN7_TXT += gitpacking.adoc +MAN7_TXT += gitnamespaces.adoc +MAN7_TXT += gitremote-helpers.adoc +MAN7_TXT += gitrevisions.adoc +MAN7_TXT += gitsubmodules.adoc +MAN7_TXT += gittutorial-2.adoc +MAN7_TXT += gittutorial.adoc +MAN7_TXT += gitworkflows.adoc + +HOWTO_TXT += $(wildcard howto/*.adoc) + +DOC_DEP_TXT += $(wildcard *.adoc) +DOC_DEP_TXT += $(wildcard config/*.adoc) +DOC_DEP_TXT += $(wildcard includes/*.adoc) ifdef MAN_FILTER MAN_TXT = $(filter $(MAN_FILTER),$(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)) @@ -75,8 +78,8 @@ MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) MAN_FILTER = $(MAN_TXT) endif -MAN_XML = $(patsubst %.txt,%.xml,$(MAN_TXT)) -MAN_HTML = $(patsubst %.txt,%.html,$(MAN_TXT)) +MAN_XML = $(patsubst %.adoc,%.xml,$(MAN_TXT)) +MAN_HTML = $(patsubst %.adoc,%.html,$(MAN_TXT)) GIT_MAN_REF = master OBSOLETE_HTML += everyday.html @@ -103,7 +106,7 @@ SP_ARTICLES += howto/rebase-from-internal-branch SP_ARTICLES += howto/keep-canonical-history-correct SP_ARTICLES += howto/maintain-git SP_ARTICLES += howto/coordinate-embargoed-releases -API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt))) +API_DOCS = $(patsubst %.adoc,%,$(filter-out technical/api-index-skel.adoc technical/api-index.adoc, $(wildcard technical/api-*.adoc))) SP_ARTICLES += $(API_DOCS) TECH_DOCS += DecisionMaking @@ -136,9 +139,9 @@ ARTICLES_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES)) HTML_FILTER ?= $(ARTICLES_HTML) $(OBSOLETE_HTML) DOC_HTML = $(MAN_HTML) $(filter $(HTML_FILTER),$(ARTICLES_HTML) $(OBSOLETE_HTML)) -DOC_MAN1 = $(patsubst %.txt,%.1,$(filter $(MAN_FILTER),$(MAN1_TXT))) -DOC_MAN5 = $(patsubst %.txt,%.5,$(filter $(MAN_FILTER),$(MAN5_TXT))) -DOC_MAN7 = $(patsubst %.txt,%.7,$(filter $(MAN_FILTER),$(MAN7_TXT))) +DOC_MAN1 = $(patsubst %.adoc,%.1,$(filter $(MAN_FILTER),$(MAN1_TXT))) +DOC_MAN5 = $(patsubst %.adoc,%.5,$(filter $(MAN_FILTER),$(MAN5_TXT))) +DOC_MAN7 = $(patsubst %.adoc,%.7,$(filter $(MAN_FILTER),$(MAN7_TXT))) prefix ?= $(HOME) bindir ?= $(prefix)/bin @@ -221,6 +224,10 @@ asciidoc.conf: asciidoc.conf.in FORCE $(QUIET_GEN)$(call version_gen,"$(shell pwd)/..",$<,$@) endif +ifdef WITH_BREAKING_CHANGES +ASCIIDOC_EXTRA += -awith-breaking-changes +endif + ASCIIDOC_DEPS += docinfo.html SHELL_PATH ?= $(SHELL) @@ -238,7 +245,7 @@ DEFAULT_EDITOR_SQ = $(subst ','\'',$(DEFAULT_EDITOR)) ASCIIDOC_EXTRA += -a 'git-default-editor=$(DEFAULT_EDITOR_SQ)' endif -all: html man +all:: html man html: $(DOC_HTML) @@ -278,7 +285,7 @@ install-pdf: pdf install-html: html '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir) -mergetools_txt = mergetools-diff.txt mergetools-merge.txt +mergetools_txt = mergetools-diff.adoc mergetools-merge.adoc # # Determine "include::" file references in asciidoc files. @@ -294,18 +301,18 @@ ifneq ($(MAKECMDGOALS),clean) -include doc.dep endif -cmds_txt = cmds-ancillaryinterrogators.txt \ - cmds-ancillarymanipulators.txt \ - cmds-mainporcelain.txt \ - cmds-plumbinginterrogators.txt \ - cmds-plumbingmanipulators.txt \ - cmds-synchingrepositories.txt \ - cmds-synchelpers.txt \ - cmds-guide.txt \ - cmds-developerinterfaces.txt \ - cmds-userinterfaces.txt \ - cmds-purehelpers.txt \ - cmds-foreignscminterface.txt +cmds_txt = cmds-ancillaryinterrogators.adoc \ + cmds-ancillarymanipulators.adoc \ + cmds-mainporcelain.adoc \ + cmds-plumbinginterrogators.adoc \ + cmds-plumbingmanipulators.adoc \ + cmds-synchingrepositories.adoc \ + cmds-synchelpers.adoc \ + cmds-guide.adoc \ + cmds-developerinterfaces.adoc \ + cmds-userinterfaces.adoc \ + cmds-purehelpers.adoc \ + cmds-foreignscminterface.adoc $(cmds_txt): cmd-list.made @@ -313,10 +320,10 @@ cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT) $(QUIET_GEN)$(PERL_PATH) ./cmd-list.perl .. . $(cmds_txt) && \ date >$@ -mergetools-%.txt: generate-mergetool-list.sh ../git-mergetool--lib.sh $(wildcard ../mergetools/*) -mergetools-diff.txt: +mergetools-%.adoc: generate-mergetool-list.sh ../git-mergetool--lib.sh $(wildcard ../mergetools/*) +mergetools-diff.adoc: $(QUIET_GEN)$(SHELL_PATH) ./generate-mergetool-list.sh .. diff $@ -mergetools-merge.txt: +mergetools-merge.adoc: $(QUIET_GEN)$(SHELL_PATH) ./generate-mergetool-list.sh .. merge $@ TRACK_ASCIIDOCFLAGS = $(subst ','\'',$(ASCIIDOC_COMMON):$(ASCIIDOC_HTML):$(ASCIIDOC_DOCBOOK)) @@ -333,9 +340,9 @@ clean: $(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7 $(RM) *.texi *.texi+ *.texi++ git.info gitman.info $(RM) *.pdf - $(RM) howto-index.txt howto/*.html doc.dep - $(RM) technical/*.html technical/api-index.txt - $(RM) SubmittingPatches.txt + $(RM) howto-index.adoc howto/*.html doc.dep + $(RM) technical/*.html technical/api-index.adoc + $(RM) SubmittingPatches.adoc $(RM) $(cmds_txt) $(mergetools_txt) *.made $(RM) GIT-ASCIIDOCFLAGS $(RM) asciidoc.conf asciidoctor-extensions.rb @@ -344,10 +351,10 @@ clean: docinfo.html: docinfo-html.in $(QUIET_GEN)$(RM) $@ && cat $< >$@ -$(MAN_HTML): %.html : %.txt $(ASCIIDOC_DEPS) +$(MAN_HTML): %.html : %.adoc $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_HTML) -d manpage -o $@ $< -$(OBSOLETE_HTML): %.html : %.txto $(ASCIIDOC_DEPS) +$(OBSOLETE_HTML): %.html : %.adoco $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_HTML) -o $@ $< manpage-prereqs := $(wildcard manpage*.xsl) @@ -360,22 +367,22 @@ manpage-cmd = $(QUIET_XMLTO)$(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< %.7 : %.xml $(manpage-prereqs) $(manpage-cmd) -%.xml : %.txt $(ASCIIDOC_DEPS) +%.xml : %.adoc $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_XML) -d manpage -o $@ $< -user-manual.xml: user-manual.txt $(ASCIIDOC_DEPS) +user-manual.xml: user-manual.adoc $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_XML) -d book -o $@ $< -technical/api-index.txt: technical/api-index-skel.txt \ - technical/api-index.sh $(patsubst %,%.txt,$(API_DOCS)) - $(QUIET_GEN)'$(SHELL_PATH_SQ)' technical/api-index.sh ./technical ./technical/api-index.txt +technical/api-index.adoc: technical/api-index-skel.adoc \ + technical/api-index.sh $(patsubst %,%.adoc,$(API_DOCS)) + $(QUIET_GEN)'$(SHELL_PATH_SQ)' technical/api-index.sh ./technical ./technical/api-index.adoc technical/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../ -$(patsubst %,%.html,$(API_DOCS) technical/api-index $(TECH_DOCS)): %.html : %.txt \ +$(patsubst %,%.html,$(API_DOCS) technical/api-index $(TECH_DOCS)): %.html : %.adoc \ $(ASCIIDOC_DEPS) - $(QUIET_ASCIIDOC)$(TXT_TO_HTML) $*.txt + $(QUIET_ASCIIDOC)$(TXT_TO_HTML) $*.adoc -SubmittingPatches.txt: SubmittingPatches +SubmittingPatches.adoc: SubmittingPatches $(QUIET_GEN) cp $< $@ XSLT = docbook.xsl @@ -409,19 +416,19 @@ gitman.texi: $(MAN_XML) cat-texi.perl texi.xsl gitman.info: gitman.texi $(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $< -$(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml +$(patsubst %.adoc,%.texi,$(MAN_TXT)): %.texi : %.xml $(QUIET_DB2TEXI)$(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@ -howto-index.txt: howto/howto-index.sh $(HOWTO_TXT) +howto-index.adoc: howto/howto-index.sh $(HOWTO_TXT) $(QUIET_GEN)'$(SHELL_PATH_SQ)' ./howto/howto-index.sh $(sort $(HOWTO_TXT)) >$@ -$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt $(ASCIIDOC_DEPS) - $(QUIET_ASCIIDOC)$(TXT_TO_HTML) $*.txt +$(patsubst %,%.html,$(ARTICLES)) : %.html : %.adoc $(ASCIIDOC_DEPS) + $(QUIET_ASCIIDOC)$(TXT_TO_HTML) $*.adoc WEBDOC_DEST = /pub/software/scm/git/docs howto/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../ -$(patsubst %.txt,%.html,$(HOWTO_TXT)): %.html : %.txt $(ASCIIDOC_DEPS) +$(patsubst %.adoc,%.html,$(HOWTO_TXT)): %.html : %.adoc $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC) \ sed -e '1,/^$$/d' $< | \ $(TXT_TO_HTML) - >$@ @@ -452,9 +459,9 @@ print-man1: @for i in $(MAN1_TXT); do echo $$i; done ## Lint: gitlink -LINT_DOCS_GITLINK = $(patsubst %.txt,.build/lint-docs/gitlink/%.ok,$(HOWTO_TXT) $(DOC_DEP_TXT)) +LINT_DOCS_GITLINK = $(patsubst %.adoc,.build/lint-docs/gitlink/%.ok,$(HOWTO_TXT) $(DOC_DEP_TXT)) $(LINT_DOCS_GITLINK): lint-gitlink.perl -$(LINT_DOCS_GITLINK): .build/lint-docs/gitlink/%.ok: %.txt +$(LINT_DOCS_GITLINK): .build/lint-docs/gitlink/%.ok: %.adoc $(call mkdir_p_parent_template) $(QUIET_LINT_GITLINK)$(PERL_PATH) lint-gitlink.perl \ $< \ @@ -466,17 +473,17 @@ $(LINT_DOCS_GITLINK): .build/lint-docs/gitlink/%.ok: %.txt lint-docs-gitlink: $(LINT_DOCS_GITLINK) ## Lint: man-end-blurb -LINT_DOCS_MAN_END_BLURB = $(patsubst %.txt,.build/lint-docs/man-end-blurb/%.ok,$(MAN_TXT)) +LINT_DOCS_MAN_END_BLURB = $(patsubst %.adoc,.build/lint-docs/man-end-blurb/%.ok,$(MAN_TXT)) $(LINT_DOCS_MAN_END_BLURB): lint-man-end-blurb.perl -$(LINT_DOCS_MAN_END_BLURB): .build/lint-docs/man-end-blurb/%.ok: %.txt +$(LINT_DOCS_MAN_END_BLURB): .build/lint-docs/man-end-blurb/%.ok: %.adoc $(call mkdir_p_parent_template) $(QUIET_LINT_MANEND)$(PERL_PATH) lint-man-end-blurb.perl $< >$@ .PHONY: lint-docs-man-end-blurb ## Lint: man-section-order -LINT_DOCS_MAN_SECTION_ORDER = $(patsubst %.txt,.build/lint-docs/man-section-order/%.ok,$(MAN_TXT)) +LINT_DOCS_MAN_SECTION_ORDER = $(patsubst %.adoc,.build/lint-docs/man-section-order/%.ok,$(MAN_TXT)) $(LINT_DOCS_MAN_SECTION_ORDER): lint-man-section-order.perl -$(LINT_DOCS_MAN_SECTION_ORDER): .build/lint-docs/man-section-order/%.ok: %.txt +$(LINT_DOCS_MAN_SECTION_ORDER): .build/lint-docs/man-section-order/%.ok: %.adoc $(call mkdir_p_parent_template) $(QUIET_LINT_MANSEC)$(PERL_PATH) lint-man-section-order.perl $< >$@ .PHONY: lint-docs-man-section-order @@ -485,10 +492,10 @@ lint-docs-man-section-order: $(LINT_DOCS_MAN_SECTION_ORDER) .PHONY: lint-docs-fsck-msgids LINT_DOCS_FSCK_MSGIDS = .build/lint-docs/fsck-msgids.ok $(LINT_DOCS_FSCK_MSGIDS): lint-fsck-msgids.perl -$(LINT_DOCS_FSCK_MSGIDS): ../fsck.h fsck-msgids.txt +$(LINT_DOCS_FSCK_MSGIDS): ../fsck.h fsck-msgids.adoc $(call mkdir_p_parent_template) $(QUIET_GEN)$(PERL_PATH) lint-fsck-msgids.perl \ - ../fsck.h fsck-msgids.txt $@ + ../fsck.h fsck-msgids.adoc $@ lint-docs-fsck-msgids: $(LINT_DOCS_FSCK_MSGIDS) @@ -501,11 +508,11 @@ lint-docs-meson: @mkdir -p tmp-meson-diff && \ awk "/^manpages = {$$/ {flag=1 ; next } /^}$$/ { flag=0 } flag { gsub(/^ \047/, \"\"); gsub(/\047 : [157],\$$/, \"\"); print }" meson.build | \ grep -v -e '#' -e '^$$' | \ - sort >tmp-meson-diff/meson.txt && \ - ls git*.txt scalar.txt | grep -v -e git-bisect-lk2009.txt -e git-tools.txt >tmp-meson-diff/actual.txt && \ - if ! cmp tmp-meson-diff/meson.txt tmp-meson-diff/actual.txt; then \ + sort >tmp-meson-diff/meson.adoc && \ + ls git*.adoc scalar.adoc | grep -v -e git-bisect-lk2009.adoc -e git-pack-redundant.adoc -e git-tools.adoc >tmp-meson-diff/actual.adoc && \ + if ! cmp tmp-meson-diff/meson.adoc tmp-meson-diff/actual.adoc; then \ echo "Meson man pages differ from actual man pages:"; \ - diff -u tmp-meson-diff/meson.txt tmp-meson-diff/actual.txt; \ + diff -u tmp-meson-diff/meson.adoc tmp-meson-diff/actual.adoc; \ exit 1; \ fi diff --git a/Documentation/MyFirstContribution.txt b/Documentation/MyFirstContribution.adoc index e41654c00a..ca1d688c9b 100644 --- a/Documentation/MyFirstContribution.txt +++ b/Documentation/MyFirstContribution.adoc @@ -21,7 +21,7 @@ This tutorial aims to summarize the following documents, but the reader may find useful additional context: - `Documentation/SubmittingPatches` -- `Documentation/howto/new-command.txt` +- `Documentation/howto/new-command.adoc` [[getting-help]] === Getting Help @@ -331,7 +331,7 @@ function body: apply standard precedence rules. `git_config_get_string_tmp()` will look up a specific key ("user.name") and give you the value. There are a number of single-key lookup functions like this one; you can see them all (and more info -about how to use `git_config()`) in `Documentation/technical/api-config.txt`. +about how to use `git_config()`) in `Documentation/technical/api-config.adoc`. You should see that the name printed matches the one you see when you run: @@ -367,6 +367,7 @@ But as we drill down, we can find that `status_init_config()` wraps a call to `git_config()`. Let's modify the code we wrote in the previous commit. Be sure to include the header to allow you to use `struct wt_status`: + ---- #include "wt-status.h" ---- @@ -461,10 +462,10 @@ $ ./bin-wrappers/git help psuh Your new command is undocumented! Let's fix that. -Take a look at `Documentation/git-*.txt`. These are the manpages for the +Take a look at `Documentation/git-*.adoc`. These are the manpages for the subcommands that Git knows about. You can open these up and take a look to get acquainted with the format, but then go ahead and make a new file -`Documentation/git-psuh.txt`. Like with most of the documentation in the Git +`Documentation/git-psuh.adoc`. Like with most of the documentation in the Git project, help pages are written with AsciiDoc (see CodingGuidelines, "Writing Documentation" section). Use the following template to fill out your own manpage: @@ -543,7 +544,7 @@ Try and run `./bin-wrappers/git psuh -h`. Your command should crash at the end. That's because `-h` is a special case which your command should handle by printing usage. -Take a look at `Documentation/technical/api-parse-options.txt`. This is a handy +Take a look at `Documentation/technical/api-parse-options.adoc`. This is a handy tool for pulling out options you need to be able to handle, and it takes a usage string. @@ -1088,14 +1089,14 @@ This gives reviewers a summary of what they're in for when reviewing your topic. The one generated for `psuh` from the sample implementation looks like this: ---- - Documentation/git-psuh.txt | 40 +++++++++++++++++++++ - Makefile | 1 + - builtin.h | 1 + - builtin/psuh.c | 73 ++++++++++++++++++++++++++++++++++++++ - git.c | 1 + - t/t9999-psuh-tutorial.sh | 12 +++++++ + Documentation/git-psuh.adoc | 40 +++++++++++++++++++++ + Makefile | 1 + + builtin.h | 1 + + builtin/psuh.c | 73 ++++++++++++++++++++++++++++++++++++++ + git.c | 1 + + t/t9999-psuh-tutorial.sh | 12 +++++++ 6 files changed, 128 insertions(+) - create mode 100644 Documentation/git-psuh.txt + create mode 100644 Documentation/git-psuh.adoc create mode 100644 builtin/psuh.c create mode 100755 t/t9999-psuh-tutorial.sh ---- diff --git a/Documentation/MyFirstObjectWalk.txt b/Documentation/MyFirstObjectWalk.adoc index dec8afe5b1..bfe8f5f561 100644 --- a/Documentation/MyFirstObjectWalk.txt +++ b/Documentation/MyFirstObjectWalk.adoc @@ -15,7 +15,7 @@ revision walk is used for operations like `git log`. === Related Reading -- `Documentation/user-manual.txt` under "Hacking Git" contains some coverage of +- `Documentation/user-manual.adoc` under "Hacking Git" contains some coverage of the revision walker in its various incarnations. - `revision.h` - https://eagain.net/articles/git-for-computer-scientists/[Git for Computer Scientists] @@ -112,7 +112,7 @@ $ GIT_TRACE=1 ./bin-wrappers/git walken ---- NOTE: For a more exhaustive overview of the new command process, take a look at -`Documentation/MyFirstContribution.txt`. +`Documentation/MyFirstContribution.adoc`. NOTE: A reference implementation can be found at https://github.com/nasamuffin/git/tree/revwalk. @@ -132,7 +132,7 @@ used to track the allocated size of the list. Per entry, we find: `item` is the object provided upon which to base the object walk. Items in Git -can be blobs, trees, commits, or tags. (See `Documentation/gittutorial-2.txt`.) +can be blobs, trees, commits, or tags. (See `Documentation/gittutorial-2.adoc`.) `name` is the object ID (OID) of the object - a hex string you may be familiar with from using Git to organize your source in the past. Check the tutorial @@ -141,7 +141,7 @@ from. `whence` indicates some information about what to do with the parents of the specified object. We'll explore this flag more later on; take a look at -`Documentation/revisions.txt` to get an idea of what could set the `whence` +`Documentation/revisions.adoc` to get an idea of what could set the `whence` value. `flags` are used to hint the beginning of the revision walk and are the first @@ -153,7 +153,7 @@ can be used during the walk, as well. This one is quite a bit longer, and many fields are only used during the walk by `revision.c` - not configuration options. Most of the configurable flags in -`struct rev_info` have a mirror in `Documentation/rev-list-options.txt`. It's a +`struct rev_info` have a mirror in `Documentation/rev-list-options.adoc`. It's a good idea to take some time and read through that document. == Basic Commit Walk @@ -287,6 +287,7 @@ static void final_rev_info_setup(struct rev_info *rev) ==== Instead of using the shorthand `add_head_to_pending()`, you could do something like this: + ---- struct setup_revision_opt opt; @@ -295,6 +296,7 @@ something like this: opt.revarg_opt = REVARG_COMMITTISH; setup_revisions(argc, argv, rev, &opt); ---- + Using a `setup_revision_opt` gives you finer control over your walk's starting point. ==== @@ -710,7 +712,7 @@ objects grows along with the Git project. === Adding a Filter There are a handful of filters that we can apply to the object walk laid out in -`Documentation/rev-list-options.txt`. These filters are typically useful for +`Documentation/rev-list-options.adoc`. These filters are typically useful for operations such as creating packfiles or performing a partial clone. They are defined in `list-objects-filter-options.h`. For the purposes of this tutorial we will use the "tree:1" filter, which causes the walk to omit all trees and blobs diff --git a/Documentation/RelNotes/1.5.0.1.txt b/Documentation/RelNotes/1.5.0.1.adoc index fea3f9935b..fea3f9935b 100644 --- a/Documentation/RelNotes/1.5.0.1.txt +++ b/Documentation/RelNotes/1.5.0.1.adoc diff --git a/Documentation/RelNotes/1.5.0.2.txt b/Documentation/RelNotes/1.5.0.2.adoc index b061e50ff0..b061e50ff0 100644 --- a/Documentation/RelNotes/1.5.0.2.txt +++ b/Documentation/RelNotes/1.5.0.2.adoc diff --git a/Documentation/RelNotes/1.5.0.3.txt b/Documentation/RelNotes/1.5.0.3.adoc index cd500f96bf..cd500f96bf 100644 --- a/Documentation/RelNotes/1.5.0.3.txt +++ b/Documentation/RelNotes/1.5.0.3.adoc diff --git a/Documentation/RelNotes/1.5.0.4.txt b/Documentation/RelNotes/1.5.0.4.adoc index feefa5dfd4..feefa5dfd4 100644 --- a/Documentation/RelNotes/1.5.0.4.txt +++ b/Documentation/RelNotes/1.5.0.4.adoc diff --git a/Documentation/RelNotes/1.5.0.5.txt b/Documentation/RelNotes/1.5.0.5.adoc index eeec3d73d0..eeec3d73d0 100644 --- a/Documentation/RelNotes/1.5.0.5.txt +++ b/Documentation/RelNotes/1.5.0.5.adoc diff --git a/Documentation/RelNotes/1.5.0.6.txt b/Documentation/RelNotes/1.5.0.6.adoc index c02015ad5f..c02015ad5f 100644 --- a/Documentation/RelNotes/1.5.0.6.txt +++ b/Documentation/RelNotes/1.5.0.6.adoc diff --git a/Documentation/RelNotes/1.5.0.7.txt b/Documentation/RelNotes/1.5.0.7.adoc index 670ad32b85..670ad32b85 100644 --- a/Documentation/RelNotes/1.5.0.7.txt +++ b/Documentation/RelNotes/1.5.0.7.adoc diff --git a/Documentation/RelNotes/1.5.0.txt b/Documentation/RelNotes/1.5.0.adoc index d6d42f3183..d6d42f3183 100644 --- a/Documentation/RelNotes/1.5.0.txt +++ b/Documentation/RelNotes/1.5.0.adoc diff --git a/Documentation/RelNotes/1.5.1.1.txt b/Documentation/RelNotes/1.5.1.1.adoc index 91471213bd..91471213bd 100644 --- a/Documentation/RelNotes/1.5.1.1.txt +++ b/Documentation/RelNotes/1.5.1.1.adoc diff --git a/Documentation/RelNotes/1.5.1.2.txt b/Documentation/RelNotes/1.5.1.2.adoc index d88456306c..d88456306c 100644 --- a/Documentation/RelNotes/1.5.1.2.txt +++ b/Documentation/RelNotes/1.5.1.2.adoc diff --git a/Documentation/RelNotes/1.5.1.3.txt b/Documentation/RelNotes/1.5.1.3.adoc index 876408b65a..876408b65a 100644 --- a/Documentation/RelNotes/1.5.1.3.txt +++ b/Documentation/RelNotes/1.5.1.3.adoc diff --git a/Documentation/RelNotes/1.5.1.4.txt b/Documentation/RelNotes/1.5.1.4.adoc index df2f66ccb5..df2f66ccb5 100644 --- a/Documentation/RelNotes/1.5.1.4.txt +++ b/Documentation/RelNotes/1.5.1.4.adoc diff --git a/Documentation/RelNotes/1.5.1.5.txt b/Documentation/RelNotes/1.5.1.5.adoc index b0ab8eb371..b0ab8eb371 100644 --- a/Documentation/RelNotes/1.5.1.5.txt +++ b/Documentation/RelNotes/1.5.1.5.adoc diff --git a/Documentation/RelNotes/1.5.1.6.txt b/Documentation/RelNotes/1.5.1.6.adoc index 55f3ac13e3..55f3ac13e3 100644 --- a/Documentation/RelNotes/1.5.1.6.txt +++ b/Documentation/RelNotes/1.5.1.6.adoc diff --git a/Documentation/RelNotes/1.5.1.txt b/Documentation/RelNotes/1.5.1.adoc index daed367270..daed367270 100644 --- a/Documentation/RelNotes/1.5.1.txt +++ b/Documentation/RelNotes/1.5.1.adoc diff --git a/Documentation/RelNotes/1.5.2.1.txt b/Documentation/RelNotes/1.5.2.1.adoc index d41984df0b..d41984df0b 100644 --- a/Documentation/RelNotes/1.5.2.1.txt +++ b/Documentation/RelNotes/1.5.2.1.adoc diff --git a/Documentation/RelNotes/1.5.2.2.txt b/Documentation/RelNotes/1.5.2.2.adoc index 7bfa341750..7bfa341750 100644 --- a/Documentation/RelNotes/1.5.2.2.txt +++ b/Documentation/RelNotes/1.5.2.2.adoc diff --git a/Documentation/RelNotes/1.5.2.3.txt b/Documentation/RelNotes/1.5.2.3.adoc index addb22955b..addb22955b 100644 --- a/Documentation/RelNotes/1.5.2.3.txt +++ b/Documentation/RelNotes/1.5.2.3.adoc diff --git a/Documentation/RelNotes/1.5.2.4.txt b/Documentation/RelNotes/1.5.2.4.adoc index 75cff475f6..75cff475f6 100644 --- a/Documentation/RelNotes/1.5.2.4.txt +++ b/Documentation/RelNotes/1.5.2.4.adoc diff --git a/Documentation/RelNotes/1.5.2.5.txt b/Documentation/RelNotes/1.5.2.5.adoc index e8281c72a0..e8281c72a0 100644 --- a/Documentation/RelNotes/1.5.2.5.txt +++ b/Documentation/RelNotes/1.5.2.5.adoc diff --git a/Documentation/RelNotes/1.5.2.txt b/Documentation/RelNotes/1.5.2.adoc index e8328d090a..e8328d090a 100644 --- a/Documentation/RelNotes/1.5.2.txt +++ b/Documentation/RelNotes/1.5.2.adoc diff --git a/Documentation/RelNotes/1.5.3.1.txt b/Documentation/RelNotes/1.5.3.1.adoc index 7ff546c743..7ff546c743 100644 --- a/Documentation/RelNotes/1.5.3.1.txt +++ b/Documentation/RelNotes/1.5.3.1.adoc diff --git a/Documentation/RelNotes/1.5.3.2.txt b/Documentation/RelNotes/1.5.3.2.adoc index 4bbde3cab4..4bbde3cab4 100644 --- a/Documentation/RelNotes/1.5.3.2.txt +++ b/Documentation/RelNotes/1.5.3.2.adoc diff --git a/Documentation/RelNotes/1.5.3.3.txt b/Documentation/RelNotes/1.5.3.3.adoc index d213846951..d213846951 100644 --- a/Documentation/RelNotes/1.5.3.3.txt +++ b/Documentation/RelNotes/1.5.3.3.adoc diff --git a/Documentation/RelNotes/1.5.3.4.txt b/Documentation/RelNotes/1.5.3.4.adoc index b04b3a45a5..b04b3a45a5 100644 --- a/Documentation/RelNotes/1.5.3.4.txt +++ b/Documentation/RelNotes/1.5.3.4.adoc diff --git a/Documentation/RelNotes/1.5.3.5.txt b/Documentation/RelNotes/1.5.3.5.adoc index 7ff1d5d0d1..7ff1d5d0d1 100644 --- a/Documentation/RelNotes/1.5.3.5.txt +++ b/Documentation/RelNotes/1.5.3.5.adoc diff --git a/Documentation/RelNotes/1.5.3.6.txt b/Documentation/RelNotes/1.5.3.6.adoc index 069a2b2cf9..069a2b2cf9 100644 --- a/Documentation/RelNotes/1.5.3.6.txt +++ b/Documentation/RelNotes/1.5.3.6.adoc diff --git a/Documentation/RelNotes/1.5.3.7.txt b/Documentation/RelNotes/1.5.3.7.adoc index 2f690616c8..2f690616c8 100644 --- a/Documentation/RelNotes/1.5.3.7.txt +++ b/Documentation/RelNotes/1.5.3.7.adoc diff --git a/Documentation/RelNotes/1.5.3.8.txt b/Documentation/RelNotes/1.5.3.8.adoc index 0e3ff58a46..0e3ff58a46 100644 --- a/Documentation/RelNotes/1.5.3.8.txt +++ b/Documentation/RelNotes/1.5.3.8.adoc diff --git a/Documentation/RelNotes/1.5.3.txt b/Documentation/RelNotes/1.5.3.adoc index 0668d3c0ca..0668d3c0ca 100644 --- a/Documentation/RelNotes/1.5.3.txt +++ b/Documentation/RelNotes/1.5.3.adoc diff --git a/Documentation/RelNotes/1.5.4.1.txt b/Documentation/RelNotes/1.5.4.1.adoc index d4e44b8b09..d4e44b8b09 100644 --- a/Documentation/RelNotes/1.5.4.1.txt +++ b/Documentation/RelNotes/1.5.4.1.adoc diff --git a/Documentation/RelNotes/1.5.4.2.txt b/Documentation/RelNotes/1.5.4.2.adoc index 21d0df59fb..21d0df59fb 100644 --- a/Documentation/RelNotes/1.5.4.2.txt +++ b/Documentation/RelNotes/1.5.4.2.adoc diff --git a/Documentation/RelNotes/1.5.4.3.txt b/Documentation/RelNotes/1.5.4.3.adoc index b0fc67fb2a..b0fc67fb2a 100644 --- a/Documentation/RelNotes/1.5.4.3.txt +++ b/Documentation/RelNotes/1.5.4.3.adoc diff --git a/Documentation/RelNotes/1.5.4.4.txt b/Documentation/RelNotes/1.5.4.4.adoc index 323c1a88c7..323c1a88c7 100644 --- a/Documentation/RelNotes/1.5.4.4.txt +++ b/Documentation/RelNotes/1.5.4.4.adoc diff --git a/Documentation/RelNotes/1.5.4.5.txt b/Documentation/RelNotes/1.5.4.5.adoc index bbd130e36d..bbd130e36d 100644 --- a/Documentation/RelNotes/1.5.4.5.txt +++ b/Documentation/RelNotes/1.5.4.5.adoc diff --git a/Documentation/RelNotes/1.5.4.6.txt b/Documentation/RelNotes/1.5.4.6.adoc index 3e3c3e55a3..3e3c3e55a3 100644 --- a/Documentation/RelNotes/1.5.4.6.txt +++ b/Documentation/RelNotes/1.5.4.6.adoc diff --git a/Documentation/RelNotes/1.5.4.7.txt b/Documentation/RelNotes/1.5.4.7.adoc index 9065a0e273..9065a0e273 100644 --- a/Documentation/RelNotes/1.5.4.7.txt +++ b/Documentation/RelNotes/1.5.4.7.adoc diff --git a/Documentation/RelNotes/1.5.4.txt b/Documentation/RelNotes/1.5.4.adoc index f1323b6174..f1323b6174 100644 --- a/Documentation/RelNotes/1.5.4.txt +++ b/Documentation/RelNotes/1.5.4.adoc diff --git a/Documentation/RelNotes/1.5.5.1.txt b/Documentation/RelNotes/1.5.5.1.adoc index 7de419708f..7de419708f 100644 --- a/Documentation/RelNotes/1.5.5.1.txt +++ b/Documentation/RelNotes/1.5.5.1.adoc diff --git a/Documentation/RelNotes/1.5.5.2.txt b/Documentation/RelNotes/1.5.5.2.adoc index 391a7b02ea..391a7b02ea 100644 --- a/Documentation/RelNotes/1.5.5.2.txt +++ b/Documentation/RelNotes/1.5.5.2.adoc diff --git a/Documentation/RelNotes/1.5.5.3.txt b/Documentation/RelNotes/1.5.5.3.adoc index f22f98b734..f22f98b734 100644 --- a/Documentation/RelNotes/1.5.5.3.txt +++ b/Documentation/RelNotes/1.5.5.3.adoc diff --git a/Documentation/RelNotes/1.5.5.4.txt b/Documentation/RelNotes/1.5.5.4.adoc index 2d0279ecce..2d0279ecce 100644 --- a/Documentation/RelNotes/1.5.5.4.txt +++ b/Documentation/RelNotes/1.5.5.4.adoc diff --git a/Documentation/RelNotes/1.5.5.5.txt b/Documentation/RelNotes/1.5.5.5.adoc index 30fa3615c7..30fa3615c7 100644 --- a/Documentation/RelNotes/1.5.5.5.txt +++ b/Documentation/RelNotes/1.5.5.5.adoc diff --git a/Documentation/RelNotes/1.5.5.6.txt b/Documentation/RelNotes/1.5.5.6.adoc index d5e85cb70e..d5e85cb70e 100644 --- a/Documentation/RelNotes/1.5.5.6.txt +++ b/Documentation/RelNotes/1.5.5.6.adoc diff --git a/Documentation/RelNotes/1.5.5.txt b/Documentation/RelNotes/1.5.5.adoc index 2932212488..2932212488 100644 --- a/Documentation/RelNotes/1.5.5.txt +++ b/Documentation/RelNotes/1.5.5.adoc diff --git a/Documentation/RelNotes/1.5.6.1.txt b/Documentation/RelNotes/1.5.6.1.adoc index 4864b16445..4864b16445 100644 --- a/Documentation/RelNotes/1.5.6.1.txt +++ b/Documentation/RelNotes/1.5.6.1.adoc diff --git a/Documentation/RelNotes/1.5.6.2.txt b/Documentation/RelNotes/1.5.6.2.adoc index 5902a85a78..5902a85a78 100644 --- a/Documentation/RelNotes/1.5.6.2.txt +++ b/Documentation/RelNotes/1.5.6.2.adoc diff --git a/Documentation/RelNotes/1.5.6.3.txt b/Documentation/RelNotes/1.5.6.3.adoc index f61dd3504a..f61dd3504a 100644 --- a/Documentation/RelNotes/1.5.6.3.txt +++ b/Documentation/RelNotes/1.5.6.3.adoc diff --git a/Documentation/RelNotes/1.5.6.4.txt b/Documentation/RelNotes/1.5.6.4.adoc index d8968f1ecb..d8968f1ecb 100644 --- a/Documentation/RelNotes/1.5.6.4.txt +++ b/Documentation/RelNotes/1.5.6.4.adoc diff --git a/Documentation/RelNotes/1.5.6.5.txt b/Documentation/RelNotes/1.5.6.5.adoc index 47ca172462..47ca172462 100644 --- a/Documentation/RelNotes/1.5.6.5.txt +++ b/Documentation/RelNotes/1.5.6.5.adoc diff --git a/Documentation/RelNotes/1.5.6.6.txt b/Documentation/RelNotes/1.5.6.6.adoc index 79da23db5a..79da23db5a 100644 --- a/Documentation/RelNotes/1.5.6.6.txt +++ b/Documentation/RelNotes/1.5.6.6.adoc diff --git a/Documentation/RelNotes/1.5.6.txt b/Documentation/RelNotes/1.5.6.adoc index e143d8d61b..e143d8d61b 100644 --- a/Documentation/RelNotes/1.5.6.txt +++ b/Documentation/RelNotes/1.5.6.adoc diff --git a/Documentation/RelNotes/1.6.0.1.txt b/Documentation/RelNotes/1.6.0.1.adoc index 49d7a1cafa..49d7a1cafa 100644 --- a/Documentation/RelNotes/1.6.0.1.txt +++ b/Documentation/RelNotes/1.6.0.1.adoc diff --git a/Documentation/RelNotes/1.6.0.2.txt b/Documentation/RelNotes/1.6.0.2.adoc index 7d8fb85e1b..7d8fb85e1b 100644 --- a/Documentation/RelNotes/1.6.0.2.txt +++ b/Documentation/RelNotes/1.6.0.2.adoc diff --git a/Documentation/RelNotes/1.6.0.3.txt b/Documentation/RelNotes/1.6.0.3.adoc index ad36c0f0b7..ad36c0f0b7 100644 --- a/Documentation/RelNotes/1.6.0.3.txt +++ b/Documentation/RelNotes/1.6.0.3.adoc diff --git a/Documentation/RelNotes/1.6.0.4.txt b/Documentation/RelNotes/1.6.0.4.adoc index d522661d31..d522661d31 100644 --- a/Documentation/RelNotes/1.6.0.4.txt +++ b/Documentation/RelNotes/1.6.0.4.adoc diff --git a/Documentation/RelNotes/1.6.0.5.txt b/Documentation/RelNotes/1.6.0.5.adoc index a08bb96738..a08bb96738 100644 --- a/Documentation/RelNotes/1.6.0.5.txt +++ b/Documentation/RelNotes/1.6.0.5.adoc diff --git a/Documentation/RelNotes/1.6.0.6.txt b/Documentation/RelNotes/1.6.0.6.adoc index 64ece1ffd5..64ece1ffd5 100644 --- a/Documentation/RelNotes/1.6.0.6.txt +++ b/Documentation/RelNotes/1.6.0.6.adoc diff --git a/Documentation/RelNotes/1.6.0.txt b/Documentation/RelNotes/1.6.0.adoc index de7ef166b6..de7ef166b6 100644 --- a/Documentation/RelNotes/1.6.0.txt +++ b/Documentation/RelNotes/1.6.0.adoc diff --git a/Documentation/RelNotes/1.6.1.1.txt b/Documentation/RelNotes/1.6.1.1.adoc index 8c594ba02f..8c594ba02f 100644 --- a/Documentation/RelNotes/1.6.1.1.txt +++ b/Documentation/RelNotes/1.6.1.1.adoc diff --git a/Documentation/RelNotes/1.6.1.2.txt b/Documentation/RelNotes/1.6.1.2.adoc index be37cbb858..be37cbb858 100644 --- a/Documentation/RelNotes/1.6.1.2.txt +++ b/Documentation/RelNotes/1.6.1.2.adoc diff --git a/Documentation/RelNotes/1.6.1.3.txt b/Documentation/RelNotes/1.6.1.3.adoc index cd08d8174e..cd08d8174e 100644 --- a/Documentation/RelNotes/1.6.1.3.txt +++ b/Documentation/RelNotes/1.6.1.3.adoc diff --git a/Documentation/RelNotes/1.6.1.4.txt b/Documentation/RelNotes/1.6.1.4.adoc index ccbad794c0..ccbad794c0 100644 --- a/Documentation/RelNotes/1.6.1.4.txt +++ b/Documentation/RelNotes/1.6.1.4.adoc diff --git a/Documentation/RelNotes/1.6.1.txt b/Documentation/RelNotes/1.6.1.adoc index 7b152a6fdc..7b152a6fdc 100644 --- a/Documentation/RelNotes/1.6.1.txt +++ b/Documentation/RelNotes/1.6.1.adoc diff --git a/Documentation/RelNotes/1.6.2.1.txt b/Documentation/RelNotes/1.6.2.1.adoc index dfa36416af..dfa36416af 100644 --- a/Documentation/RelNotes/1.6.2.1.txt +++ b/Documentation/RelNotes/1.6.2.1.adoc diff --git a/Documentation/RelNotes/1.6.2.2.txt b/Documentation/RelNotes/1.6.2.2.adoc index fafa9986b0..fafa9986b0 100644 --- a/Documentation/RelNotes/1.6.2.2.txt +++ b/Documentation/RelNotes/1.6.2.2.adoc diff --git a/Documentation/RelNotes/1.6.2.3.txt b/Documentation/RelNotes/1.6.2.3.adoc index 4d3c1ac91c..4d3c1ac91c 100644 --- a/Documentation/RelNotes/1.6.2.3.txt +++ b/Documentation/RelNotes/1.6.2.3.adoc diff --git a/Documentation/RelNotes/1.6.2.4.txt b/Documentation/RelNotes/1.6.2.4.adoc index f4bf1d0986..f4bf1d0986 100644 --- a/Documentation/RelNotes/1.6.2.4.txt +++ b/Documentation/RelNotes/1.6.2.4.adoc diff --git a/Documentation/RelNotes/1.6.2.5.txt b/Documentation/RelNotes/1.6.2.5.adoc index b23f9e95d1..b23f9e95d1 100644 --- a/Documentation/RelNotes/1.6.2.5.txt +++ b/Documentation/RelNotes/1.6.2.5.adoc diff --git a/Documentation/RelNotes/1.6.2.txt b/Documentation/RelNotes/1.6.2.adoc index 166d73c60f..166d73c60f 100644 --- a/Documentation/RelNotes/1.6.2.txt +++ b/Documentation/RelNotes/1.6.2.adoc diff --git a/Documentation/RelNotes/1.6.3.1.txt b/Documentation/RelNotes/1.6.3.1.adoc index 2400b72ef7..2400b72ef7 100644 --- a/Documentation/RelNotes/1.6.3.1.txt +++ b/Documentation/RelNotes/1.6.3.1.adoc diff --git a/Documentation/RelNotes/1.6.3.2.txt b/Documentation/RelNotes/1.6.3.2.adoc index b2f3f0293c..b2f3f0293c 100644 --- a/Documentation/RelNotes/1.6.3.2.txt +++ b/Documentation/RelNotes/1.6.3.2.adoc diff --git a/Documentation/RelNotes/1.6.3.3.txt b/Documentation/RelNotes/1.6.3.3.adoc index 1c28398bb6..1c28398bb6 100644 --- a/Documentation/RelNotes/1.6.3.3.txt +++ b/Documentation/RelNotes/1.6.3.3.adoc diff --git a/Documentation/RelNotes/1.6.3.4.txt b/Documentation/RelNotes/1.6.3.4.adoc index cad461bc76..cad461bc76 100644 --- a/Documentation/RelNotes/1.6.3.4.txt +++ b/Documentation/RelNotes/1.6.3.4.adoc diff --git a/Documentation/RelNotes/1.6.3.txt b/Documentation/RelNotes/1.6.3.adoc index bbf177fc3c..bbf177fc3c 100644 --- a/Documentation/RelNotes/1.6.3.txt +++ b/Documentation/RelNotes/1.6.3.adoc diff --git a/Documentation/RelNotes/1.6.4.1.txt b/Documentation/RelNotes/1.6.4.1.adoc index e439e45b96..e439e45b96 100644 --- a/Documentation/RelNotes/1.6.4.1.txt +++ b/Documentation/RelNotes/1.6.4.1.adoc diff --git a/Documentation/RelNotes/1.6.4.2.txt b/Documentation/RelNotes/1.6.4.2.adoc index c11ec0115c..c11ec0115c 100644 --- a/Documentation/RelNotes/1.6.4.2.txt +++ b/Documentation/RelNotes/1.6.4.2.adoc diff --git a/Documentation/RelNotes/1.6.4.3.txt b/Documentation/RelNotes/1.6.4.3.adoc index 5643e6537d..5643e6537d 100644 --- a/Documentation/RelNotes/1.6.4.3.txt +++ b/Documentation/RelNotes/1.6.4.3.adoc diff --git a/Documentation/RelNotes/1.6.4.4.txt b/Documentation/RelNotes/1.6.4.4.adoc index 0ead45fc72..0ead45fc72 100644 --- a/Documentation/RelNotes/1.6.4.4.txt +++ b/Documentation/RelNotes/1.6.4.4.adoc diff --git a/Documentation/RelNotes/1.6.4.5.txt b/Documentation/RelNotes/1.6.4.5.adoc index eb6307dcbb..eb6307dcbb 100644 --- a/Documentation/RelNotes/1.6.4.5.txt +++ b/Documentation/RelNotes/1.6.4.5.adoc diff --git a/Documentation/RelNotes/1.6.4.txt b/Documentation/RelNotes/1.6.4.adoc index 0fccfb0bf0..0fccfb0bf0 100644 --- a/Documentation/RelNotes/1.6.4.txt +++ b/Documentation/RelNotes/1.6.4.adoc diff --git a/Documentation/RelNotes/1.6.5.1.txt b/Documentation/RelNotes/1.6.5.1.adoc index 309ba181b2..309ba181b2 100644 --- a/Documentation/RelNotes/1.6.5.1.txt +++ b/Documentation/RelNotes/1.6.5.1.adoc diff --git a/Documentation/RelNotes/1.6.5.2.txt b/Documentation/RelNotes/1.6.5.2.adoc index aa7ccce3a2..aa7ccce3a2 100644 --- a/Documentation/RelNotes/1.6.5.2.txt +++ b/Documentation/RelNotes/1.6.5.2.adoc diff --git a/Documentation/RelNotes/1.6.5.3.txt b/Documentation/RelNotes/1.6.5.3.adoc index b2fad1b22e..b2fad1b22e 100644 --- a/Documentation/RelNotes/1.6.5.3.txt +++ b/Documentation/RelNotes/1.6.5.3.adoc diff --git a/Documentation/RelNotes/1.6.5.4.txt b/Documentation/RelNotes/1.6.5.4.adoc index 344333de66..344333de66 100644 --- a/Documentation/RelNotes/1.6.5.4.txt +++ b/Documentation/RelNotes/1.6.5.4.adoc diff --git a/Documentation/RelNotes/1.6.5.5.txt b/Documentation/RelNotes/1.6.5.5.adoc index ecfc57d875..ecfc57d875 100644 --- a/Documentation/RelNotes/1.6.5.5.txt +++ b/Documentation/RelNotes/1.6.5.5.adoc diff --git a/Documentation/RelNotes/1.6.5.6.txt b/Documentation/RelNotes/1.6.5.6.adoc index a9eaf76f62..a9eaf76f62 100644 --- a/Documentation/RelNotes/1.6.5.6.txt +++ b/Documentation/RelNotes/1.6.5.6.adoc diff --git a/Documentation/RelNotes/1.6.5.7.txt b/Documentation/RelNotes/1.6.5.7.adoc index dc5302c21c..dc5302c21c 100644 --- a/Documentation/RelNotes/1.6.5.7.txt +++ b/Documentation/RelNotes/1.6.5.7.adoc diff --git a/Documentation/RelNotes/1.6.5.8.txt b/Documentation/RelNotes/1.6.5.8.adoc index 8b24bebb96..8b24bebb96 100644 --- a/Documentation/RelNotes/1.6.5.8.txt +++ b/Documentation/RelNotes/1.6.5.8.adoc diff --git a/Documentation/RelNotes/1.6.5.9.txt b/Documentation/RelNotes/1.6.5.9.adoc index bb469dd71e..bb469dd71e 100644 --- a/Documentation/RelNotes/1.6.5.9.txt +++ b/Documentation/RelNotes/1.6.5.9.adoc diff --git a/Documentation/RelNotes/1.6.5.txt b/Documentation/RelNotes/1.6.5.adoc index 79cb1b2b6d..79cb1b2b6d 100644 --- a/Documentation/RelNotes/1.6.5.txt +++ b/Documentation/RelNotes/1.6.5.adoc diff --git a/Documentation/RelNotes/1.6.6.1.txt b/Documentation/RelNotes/1.6.6.1.adoc index f1d0a4ae2d..f1d0a4ae2d 100644 --- a/Documentation/RelNotes/1.6.6.1.txt +++ b/Documentation/RelNotes/1.6.6.1.adoc diff --git a/Documentation/RelNotes/1.6.6.2.txt b/Documentation/RelNotes/1.6.6.2.adoc index 4eaddc0106..4eaddc0106 100644 --- a/Documentation/RelNotes/1.6.6.2.txt +++ b/Documentation/RelNotes/1.6.6.2.adoc diff --git a/Documentation/RelNotes/1.6.6.3.txt b/Documentation/RelNotes/1.6.6.3.adoc index 11483acaec..11483acaec 100644 --- a/Documentation/RelNotes/1.6.6.3.txt +++ b/Documentation/RelNotes/1.6.6.3.adoc diff --git a/Documentation/RelNotes/1.6.6.txt b/Documentation/RelNotes/1.6.6.adoc index 88b86a827e..88b86a827e 100644 --- a/Documentation/RelNotes/1.6.6.txt +++ b/Documentation/RelNotes/1.6.6.adoc diff --git a/Documentation/RelNotes/1.7.0.1.txt b/Documentation/RelNotes/1.7.0.1.adoc index 8ff5bcada8..8ff5bcada8 100644 --- a/Documentation/RelNotes/1.7.0.1.txt +++ b/Documentation/RelNotes/1.7.0.1.adoc diff --git a/Documentation/RelNotes/1.7.0.2.txt b/Documentation/RelNotes/1.7.0.2.adoc index 73ed2b5278..73ed2b5278 100644 --- a/Documentation/RelNotes/1.7.0.2.txt +++ b/Documentation/RelNotes/1.7.0.2.adoc diff --git a/Documentation/RelNotes/1.7.0.3.txt b/Documentation/RelNotes/1.7.0.3.adoc index 3b355737c0..3b355737c0 100644 --- a/Documentation/RelNotes/1.7.0.3.txt +++ b/Documentation/RelNotes/1.7.0.3.adoc diff --git a/Documentation/RelNotes/1.7.0.4.txt b/Documentation/RelNotes/1.7.0.4.adoc index cf7f60e60d..cf7f60e60d 100644 --- a/Documentation/RelNotes/1.7.0.4.txt +++ b/Documentation/RelNotes/1.7.0.4.adoc diff --git a/Documentation/RelNotes/1.7.0.5.txt b/Documentation/RelNotes/1.7.0.5.adoc index 3149c91b7b..3149c91b7b 100644 --- a/Documentation/RelNotes/1.7.0.5.txt +++ b/Documentation/RelNotes/1.7.0.5.adoc diff --git a/Documentation/RelNotes/1.7.0.6.txt b/Documentation/RelNotes/1.7.0.6.adoc index b2852b67d0..b2852b67d0 100644 --- a/Documentation/RelNotes/1.7.0.6.txt +++ b/Documentation/RelNotes/1.7.0.6.adoc diff --git a/Documentation/RelNotes/1.7.0.7.txt b/Documentation/RelNotes/1.7.0.7.adoc index d0cb7ca7e2..d0cb7ca7e2 100644 --- a/Documentation/RelNotes/1.7.0.7.txt +++ b/Documentation/RelNotes/1.7.0.7.adoc diff --git a/Documentation/RelNotes/1.7.0.8.txt b/Documentation/RelNotes/1.7.0.8.adoc index 7f05b48e17..7f05b48e17 100644 --- a/Documentation/RelNotes/1.7.0.8.txt +++ b/Documentation/RelNotes/1.7.0.8.adoc diff --git a/Documentation/RelNotes/1.7.0.9.txt b/Documentation/RelNotes/1.7.0.9.adoc index bfb3166387..bfb3166387 100644 --- a/Documentation/RelNotes/1.7.0.9.txt +++ b/Documentation/RelNotes/1.7.0.9.adoc diff --git a/Documentation/RelNotes/1.7.0.txt b/Documentation/RelNotes/1.7.0.adoc index 0bb8c0b2a2..0bb8c0b2a2 100644 --- a/Documentation/RelNotes/1.7.0.txt +++ b/Documentation/RelNotes/1.7.0.adoc diff --git a/Documentation/RelNotes/1.7.1.1.txt b/Documentation/RelNotes/1.7.1.1.adoc index 3f6b3148a3..3f6b3148a3 100644 --- a/Documentation/RelNotes/1.7.1.1.txt +++ b/Documentation/RelNotes/1.7.1.1.adoc diff --git a/Documentation/RelNotes/1.7.1.2.txt b/Documentation/RelNotes/1.7.1.2.adoc index 61ba14e262..61ba14e262 100644 --- a/Documentation/RelNotes/1.7.1.2.txt +++ b/Documentation/RelNotes/1.7.1.2.adoc diff --git a/Documentation/RelNotes/1.7.1.3.txt b/Documentation/RelNotes/1.7.1.3.adoc index 5b18518449..5b18518449 100644 --- a/Documentation/RelNotes/1.7.1.3.txt +++ b/Documentation/RelNotes/1.7.1.3.adoc diff --git a/Documentation/RelNotes/1.7.1.4.txt b/Documentation/RelNotes/1.7.1.4.adoc index 7c734b4f7b..7c734b4f7b 100644 --- a/Documentation/RelNotes/1.7.1.4.txt +++ b/Documentation/RelNotes/1.7.1.4.adoc diff --git a/Documentation/RelNotes/1.7.1.txt b/Documentation/RelNotes/1.7.1.adoc index 9d89fedb36..9d89fedb36 100644 --- a/Documentation/RelNotes/1.7.1.txt +++ b/Documentation/RelNotes/1.7.1.adoc diff --git a/Documentation/RelNotes/1.7.10.1.txt b/Documentation/RelNotes/1.7.10.1.adoc index 71a86cb7c6..71a86cb7c6 100644 --- a/Documentation/RelNotes/1.7.10.1.txt +++ b/Documentation/RelNotes/1.7.10.1.adoc diff --git a/Documentation/RelNotes/1.7.10.2.txt b/Documentation/RelNotes/1.7.10.2.adoc index 7a7e9d6fd1..7a7e9d6fd1 100644 --- a/Documentation/RelNotes/1.7.10.2.txt +++ b/Documentation/RelNotes/1.7.10.2.adoc diff --git a/Documentation/RelNotes/1.7.10.3.txt b/Documentation/RelNotes/1.7.10.3.adoc index 703fbf1d60..703fbf1d60 100644 --- a/Documentation/RelNotes/1.7.10.3.txt +++ b/Documentation/RelNotes/1.7.10.3.adoc diff --git a/Documentation/RelNotes/1.7.10.4.txt b/Documentation/RelNotes/1.7.10.4.adoc index 57597f2bf3..57597f2bf3 100644 --- a/Documentation/RelNotes/1.7.10.4.txt +++ b/Documentation/RelNotes/1.7.10.4.adoc diff --git a/Documentation/RelNotes/1.7.10.5.txt b/Documentation/RelNotes/1.7.10.5.adoc index 4db1770e38..4db1770e38 100644 --- a/Documentation/RelNotes/1.7.10.5.txt +++ b/Documentation/RelNotes/1.7.10.5.adoc diff --git a/Documentation/RelNotes/1.7.10.txt b/Documentation/RelNotes/1.7.10.adoc index 58100bf04e..58100bf04e 100644 --- a/Documentation/RelNotes/1.7.10.txt +++ b/Documentation/RelNotes/1.7.10.adoc diff --git a/Documentation/RelNotes/1.7.11.1.txt b/Documentation/RelNotes/1.7.11.1.adoc index 577eccaacd..577eccaacd 100644 --- a/Documentation/RelNotes/1.7.11.1.txt +++ b/Documentation/RelNotes/1.7.11.1.adoc diff --git a/Documentation/RelNotes/1.7.11.2.txt b/Documentation/RelNotes/1.7.11.2.adoc index f0cfd02d6f..f0cfd02d6f 100644 --- a/Documentation/RelNotes/1.7.11.2.txt +++ b/Documentation/RelNotes/1.7.11.2.adoc diff --git a/Documentation/RelNotes/1.7.11.3.txt b/Documentation/RelNotes/1.7.11.3.adoc index 64494f89d9..64494f89d9 100644 --- a/Documentation/RelNotes/1.7.11.3.txt +++ b/Documentation/RelNotes/1.7.11.3.adoc diff --git a/Documentation/RelNotes/1.7.11.4.txt b/Documentation/RelNotes/1.7.11.4.adoc index 3a640c2d4d..3a640c2d4d 100644 --- a/Documentation/RelNotes/1.7.11.4.txt +++ b/Documentation/RelNotes/1.7.11.4.adoc diff --git a/Documentation/RelNotes/1.7.11.5.txt b/Documentation/RelNotes/1.7.11.5.adoc index 0a2ed855c5..0a2ed855c5 100644 --- a/Documentation/RelNotes/1.7.11.5.txt +++ b/Documentation/RelNotes/1.7.11.5.adoc diff --git a/Documentation/RelNotes/1.7.11.6.txt b/Documentation/RelNotes/1.7.11.6.adoc index ba7d3c3966..ba7d3c3966 100644 --- a/Documentation/RelNotes/1.7.11.6.txt +++ b/Documentation/RelNotes/1.7.11.6.adoc diff --git a/Documentation/RelNotes/1.7.11.7.txt b/Documentation/RelNotes/1.7.11.7.adoc index e743a2a8e4..e743a2a8e4 100644 --- a/Documentation/RelNotes/1.7.11.7.txt +++ b/Documentation/RelNotes/1.7.11.7.adoc diff --git a/Documentation/RelNotes/1.7.11.txt b/Documentation/RelNotes/1.7.11.adoc index 15b954ca4b..15b954ca4b 100644 --- a/Documentation/RelNotes/1.7.11.txt +++ b/Documentation/RelNotes/1.7.11.adoc diff --git a/Documentation/RelNotes/1.7.12.1.txt b/Documentation/RelNotes/1.7.12.1.adoc index b8f04af19f..b8f04af19f 100644 --- a/Documentation/RelNotes/1.7.12.1.txt +++ b/Documentation/RelNotes/1.7.12.1.adoc diff --git a/Documentation/RelNotes/1.7.12.2.txt b/Documentation/RelNotes/1.7.12.2.adoc index 69255745e6..69255745e6 100644 --- a/Documentation/RelNotes/1.7.12.2.txt +++ b/Documentation/RelNotes/1.7.12.2.adoc diff --git a/Documentation/RelNotes/1.7.12.3.txt b/Documentation/RelNotes/1.7.12.3.adoc index 4b822976b8..4b822976b8 100644 --- a/Documentation/RelNotes/1.7.12.3.txt +++ b/Documentation/RelNotes/1.7.12.3.adoc diff --git a/Documentation/RelNotes/1.7.12.4.txt b/Documentation/RelNotes/1.7.12.4.adoc index c6da3cc939..c6da3cc939 100644 --- a/Documentation/RelNotes/1.7.12.4.txt +++ b/Documentation/RelNotes/1.7.12.4.adoc diff --git a/Documentation/RelNotes/1.7.12.txt b/Documentation/RelNotes/1.7.12.adoc index 010d8c7de4..010d8c7de4 100644 --- a/Documentation/RelNotes/1.7.12.txt +++ b/Documentation/RelNotes/1.7.12.adoc diff --git a/Documentation/RelNotes/1.7.2.1.txt b/Documentation/RelNotes/1.7.2.1.adoc index 1103c47a4f..1103c47a4f 100644 --- a/Documentation/RelNotes/1.7.2.1.txt +++ b/Documentation/RelNotes/1.7.2.1.adoc diff --git a/Documentation/RelNotes/1.7.2.2.txt b/Documentation/RelNotes/1.7.2.2.adoc index 71eb6a8b0a..71eb6a8b0a 100644 --- a/Documentation/RelNotes/1.7.2.2.txt +++ b/Documentation/RelNotes/1.7.2.2.adoc diff --git a/Documentation/RelNotes/1.7.2.3.txt b/Documentation/RelNotes/1.7.2.3.adoc index 610960cfe1..610960cfe1 100644 --- a/Documentation/RelNotes/1.7.2.3.txt +++ b/Documentation/RelNotes/1.7.2.3.adoc diff --git a/Documentation/RelNotes/1.7.2.4.txt b/Documentation/RelNotes/1.7.2.4.adoc index f7950a4c04..f7950a4c04 100644 --- a/Documentation/RelNotes/1.7.2.4.txt +++ b/Documentation/RelNotes/1.7.2.4.adoc diff --git a/Documentation/RelNotes/1.7.2.5.txt b/Documentation/RelNotes/1.7.2.5.adoc index bf976c40db..bf976c40db 100644 --- a/Documentation/RelNotes/1.7.2.5.txt +++ b/Documentation/RelNotes/1.7.2.5.adoc diff --git a/Documentation/RelNotes/1.7.2.txt b/Documentation/RelNotes/1.7.2.adoc index 15cf01178c..15cf01178c 100644 --- a/Documentation/RelNotes/1.7.2.txt +++ b/Documentation/RelNotes/1.7.2.adoc diff --git a/Documentation/RelNotes/1.7.3.1.txt b/Documentation/RelNotes/1.7.3.1.adoc index 002c93b961..002c93b961 100644 --- a/Documentation/RelNotes/1.7.3.1.txt +++ b/Documentation/RelNotes/1.7.3.1.adoc diff --git a/Documentation/RelNotes/1.7.3.2.txt b/Documentation/RelNotes/1.7.3.2.adoc index 5c93b85af4..5c93b85af4 100644 --- a/Documentation/RelNotes/1.7.3.2.txt +++ b/Documentation/RelNotes/1.7.3.2.adoc diff --git a/Documentation/RelNotes/1.7.3.3.txt b/Documentation/RelNotes/1.7.3.3.adoc index 9b2b2448df..9b2b2448df 100644 --- a/Documentation/RelNotes/1.7.3.3.txt +++ b/Documentation/RelNotes/1.7.3.3.adoc diff --git a/Documentation/RelNotes/1.7.3.4.txt b/Documentation/RelNotes/1.7.3.4.adoc index e57f7c176d..e57f7c176d 100644 --- a/Documentation/RelNotes/1.7.3.4.txt +++ b/Documentation/RelNotes/1.7.3.4.adoc diff --git a/Documentation/RelNotes/1.7.3.5.txt b/Documentation/RelNotes/1.7.3.5.adoc index 40f3ba5795..40f3ba5795 100644 --- a/Documentation/RelNotes/1.7.3.5.txt +++ b/Documentation/RelNotes/1.7.3.5.adoc diff --git a/Documentation/RelNotes/1.7.3.txt b/Documentation/RelNotes/1.7.3.adoc index 309c33181f..309c33181f 100644 --- a/Documentation/RelNotes/1.7.3.txt +++ b/Documentation/RelNotes/1.7.3.adoc diff --git a/Documentation/RelNotes/1.7.4.1.txt b/Documentation/RelNotes/1.7.4.1.adoc index 79923a6d2f..79923a6d2f 100644 --- a/Documentation/RelNotes/1.7.4.1.txt +++ b/Documentation/RelNotes/1.7.4.1.adoc diff --git a/Documentation/RelNotes/1.7.4.2.txt b/Documentation/RelNotes/1.7.4.2.adoc index ef4ce1fcd3..ef4ce1fcd3 100644 --- a/Documentation/RelNotes/1.7.4.2.txt +++ b/Documentation/RelNotes/1.7.4.2.adoc diff --git a/Documentation/RelNotes/1.7.4.3.txt b/Documentation/RelNotes/1.7.4.3.adoc index 02a3d5bdf6..02a3d5bdf6 100644 --- a/Documentation/RelNotes/1.7.4.3.txt +++ b/Documentation/RelNotes/1.7.4.3.adoc diff --git a/Documentation/RelNotes/1.7.4.4.txt b/Documentation/RelNotes/1.7.4.4.adoc index ff06e04a58..ff06e04a58 100644 --- a/Documentation/RelNotes/1.7.4.4.txt +++ b/Documentation/RelNotes/1.7.4.4.adoc diff --git a/Documentation/RelNotes/1.7.4.5.txt b/Documentation/RelNotes/1.7.4.5.adoc index b7a0eeb22f..b7a0eeb22f 100644 --- a/Documentation/RelNotes/1.7.4.5.txt +++ b/Documentation/RelNotes/1.7.4.5.adoc diff --git a/Documentation/RelNotes/1.7.4.txt b/Documentation/RelNotes/1.7.4.adoc index d5bca731b5..d5bca731b5 100644 --- a/Documentation/RelNotes/1.7.4.txt +++ b/Documentation/RelNotes/1.7.4.adoc diff --git a/Documentation/RelNotes/1.7.5.1.txt b/Documentation/RelNotes/1.7.5.1.adoc index c6ebd76d19..c6ebd76d19 100644 --- a/Documentation/RelNotes/1.7.5.1.txt +++ b/Documentation/RelNotes/1.7.5.1.adoc diff --git a/Documentation/RelNotes/1.7.5.2.txt b/Documentation/RelNotes/1.7.5.2.adoc index 951eb7cb08..951eb7cb08 100644 --- a/Documentation/RelNotes/1.7.5.2.txt +++ b/Documentation/RelNotes/1.7.5.2.adoc diff --git a/Documentation/RelNotes/1.7.5.3.txt b/Documentation/RelNotes/1.7.5.3.adoc index 1d24edcf2f..1d24edcf2f 100644 --- a/Documentation/RelNotes/1.7.5.3.txt +++ b/Documentation/RelNotes/1.7.5.3.adoc diff --git a/Documentation/RelNotes/1.7.5.4.txt b/Documentation/RelNotes/1.7.5.4.adoc index 7796df3fe4..7796df3fe4 100644 --- a/Documentation/RelNotes/1.7.5.4.txt +++ b/Documentation/RelNotes/1.7.5.4.adoc diff --git a/Documentation/RelNotes/1.7.5.txt b/Documentation/RelNotes/1.7.5.adoc index 987919c321..987919c321 100644 --- a/Documentation/RelNotes/1.7.5.txt +++ b/Documentation/RelNotes/1.7.5.adoc diff --git a/Documentation/RelNotes/1.7.6.1.txt b/Documentation/RelNotes/1.7.6.1.adoc index 42e46ab17f..42e46ab17f 100644 --- a/Documentation/RelNotes/1.7.6.1.txt +++ b/Documentation/RelNotes/1.7.6.1.adoc diff --git a/Documentation/RelNotes/1.7.6.2.txt b/Documentation/RelNotes/1.7.6.2.adoc index 67ae414965..67ae414965 100644 --- a/Documentation/RelNotes/1.7.6.2.txt +++ b/Documentation/RelNotes/1.7.6.2.adoc diff --git a/Documentation/RelNotes/1.7.6.3.txt b/Documentation/RelNotes/1.7.6.3.adoc index 95971831b9..95971831b9 100644 --- a/Documentation/RelNotes/1.7.6.3.txt +++ b/Documentation/RelNotes/1.7.6.3.adoc diff --git a/Documentation/RelNotes/1.7.6.4.txt b/Documentation/RelNotes/1.7.6.4.adoc index e19acac2da..e19acac2da 100644 --- a/Documentation/RelNotes/1.7.6.4.txt +++ b/Documentation/RelNotes/1.7.6.4.adoc diff --git a/Documentation/RelNotes/1.7.6.5.txt b/Documentation/RelNotes/1.7.6.5.adoc index 6713132a9e..6713132a9e 100644 --- a/Documentation/RelNotes/1.7.6.5.txt +++ b/Documentation/RelNotes/1.7.6.5.adoc diff --git a/Documentation/RelNotes/1.7.6.6.txt b/Documentation/RelNotes/1.7.6.6.adoc index 5343e00400..5343e00400 100644 --- a/Documentation/RelNotes/1.7.6.6.txt +++ b/Documentation/RelNotes/1.7.6.6.adoc diff --git a/Documentation/RelNotes/1.7.6.txt b/Documentation/RelNotes/1.7.6.adoc index 9ec498ea39..9ec498ea39 100644 --- a/Documentation/RelNotes/1.7.6.txt +++ b/Documentation/RelNotes/1.7.6.adoc diff --git a/Documentation/RelNotes/1.7.7.1.txt b/Documentation/RelNotes/1.7.7.1.adoc index ac9b838e25..ac9b838e25 100644 --- a/Documentation/RelNotes/1.7.7.1.txt +++ b/Documentation/RelNotes/1.7.7.1.adoc diff --git a/Documentation/RelNotes/1.7.7.2.txt b/Documentation/RelNotes/1.7.7.2.adoc index e6bbef2f01..e6bbef2f01 100644 --- a/Documentation/RelNotes/1.7.7.2.txt +++ b/Documentation/RelNotes/1.7.7.2.adoc diff --git a/Documentation/RelNotes/1.7.7.3.txt b/Documentation/RelNotes/1.7.7.3.adoc index 09301f0957..09301f0957 100644 --- a/Documentation/RelNotes/1.7.7.3.txt +++ b/Documentation/RelNotes/1.7.7.3.adoc diff --git a/Documentation/RelNotes/1.7.7.4.txt b/Documentation/RelNotes/1.7.7.4.adoc index e5234485e7..e5234485e7 100644 --- a/Documentation/RelNotes/1.7.7.4.txt +++ b/Documentation/RelNotes/1.7.7.4.adoc diff --git a/Documentation/RelNotes/1.7.7.5.txt b/Documentation/RelNotes/1.7.7.5.adoc index 7b0931987b..7b0931987b 100644 --- a/Documentation/RelNotes/1.7.7.5.txt +++ b/Documentation/RelNotes/1.7.7.5.adoc diff --git a/Documentation/RelNotes/1.7.7.6.txt b/Documentation/RelNotes/1.7.7.6.adoc index 8df606d452..8df606d452 100644 --- a/Documentation/RelNotes/1.7.7.6.txt +++ b/Documentation/RelNotes/1.7.7.6.adoc diff --git a/Documentation/RelNotes/1.7.7.7.txt b/Documentation/RelNotes/1.7.7.7.adoc index e79118d063..e79118d063 100644 --- a/Documentation/RelNotes/1.7.7.7.txt +++ b/Documentation/RelNotes/1.7.7.7.adoc diff --git a/Documentation/RelNotes/1.7.7.txt b/Documentation/RelNotes/1.7.7.adoc index 6eff128c80..6eff128c80 100644 --- a/Documentation/RelNotes/1.7.7.txt +++ b/Documentation/RelNotes/1.7.7.adoc diff --git a/Documentation/RelNotes/1.7.8.1.txt b/Documentation/RelNotes/1.7.8.1.adoc index 33dc948b94..33dc948b94 100644 --- a/Documentation/RelNotes/1.7.8.1.txt +++ b/Documentation/RelNotes/1.7.8.1.adoc diff --git a/Documentation/RelNotes/1.7.8.2.txt b/Documentation/RelNotes/1.7.8.2.adoc index b9c66aa1b7..b9c66aa1b7 100644 --- a/Documentation/RelNotes/1.7.8.2.txt +++ b/Documentation/RelNotes/1.7.8.2.adoc diff --git a/Documentation/RelNotes/1.7.8.3.txt b/Documentation/RelNotes/1.7.8.3.adoc index a92714c14b..a92714c14b 100644 --- a/Documentation/RelNotes/1.7.8.3.txt +++ b/Documentation/RelNotes/1.7.8.3.adoc diff --git a/Documentation/RelNotes/1.7.8.4.txt b/Documentation/RelNotes/1.7.8.4.adoc index 9bebdbf13d..9bebdbf13d 100644 --- a/Documentation/RelNotes/1.7.8.4.txt +++ b/Documentation/RelNotes/1.7.8.4.adoc diff --git a/Documentation/RelNotes/1.7.8.5.txt b/Documentation/RelNotes/1.7.8.5.adoc index 011fd2a428..011fd2a428 100644 --- a/Documentation/RelNotes/1.7.8.5.txt +++ b/Documentation/RelNotes/1.7.8.5.adoc diff --git a/Documentation/RelNotes/1.7.8.6.txt b/Documentation/RelNotes/1.7.8.6.adoc index d9bf2b741a..d9bf2b741a 100644 --- a/Documentation/RelNotes/1.7.8.6.txt +++ b/Documentation/RelNotes/1.7.8.6.adoc diff --git a/Documentation/RelNotes/1.7.8.txt b/Documentation/RelNotes/1.7.8.adoc index 249311361e..249311361e 100644 --- a/Documentation/RelNotes/1.7.8.txt +++ b/Documentation/RelNotes/1.7.8.adoc diff --git a/Documentation/RelNotes/1.7.9.1.txt b/Documentation/RelNotes/1.7.9.1.adoc index 6957183dbb..6957183dbb 100644 --- a/Documentation/RelNotes/1.7.9.1.txt +++ b/Documentation/RelNotes/1.7.9.1.adoc diff --git a/Documentation/RelNotes/1.7.9.2.txt b/Documentation/RelNotes/1.7.9.2.adoc index e500da75dd..e500da75dd 100644 --- a/Documentation/RelNotes/1.7.9.2.txt +++ b/Documentation/RelNotes/1.7.9.2.adoc diff --git a/Documentation/RelNotes/1.7.9.3.txt b/Documentation/RelNotes/1.7.9.3.adoc index 91c65012f9..91c65012f9 100644 --- a/Documentation/RelNotes/1.7.9.3.txt +++ b/Documentation/RelNotes/1.7.9.3.adoc diff --git a/Documentation/RelNotes/1.7.9.4.txt b/Documentation/RelNotes/1.7.9.4.adoc index e5217a1889..e5217a1889 100644 --- a/Documentation/RelNotes/1.7.9.4.txt +++ b/Documentation/RelNotes/1.7.9.4.adoc diff --git a/Documentation/RelNotes/1.7.9.5.txt b/Documentation/RelNotes/1.7.9.5.adoc index 95cc2bbf2c..95cc2bbf2c 100644 --- a/Documentation/RelNotes/1.7.9.5.txt +++ b/Documentation/RelNotes/1.7.9.5.adoc diff --git a/Documentation/RelNotes/1.7.9.6.txt b/Documentation/RelNotes/1.7.9.6.adoc index 74bf8825e2..74bf8825e2 100644 --- a/Documentation/RelNotes/1.7.9.6.txt +++ b/Documentation/RelNotes/1.7.9.6.adoc diff --git a/Documentation/RelNotes/1.7.9.7.txt b/Documentation/RelNotes/1.7.9.7.adoc index 59667d0f2a..59667d0f2a 100644 --- a/Documentation/RelNotes/1.7.9.7.txt +++ b/Documentation/RelNotes/1.7.9.7.adoc diff --git a/Documentation/RelNotes/1.7.9.txt b/Documentation/RelNotes/1.7.9.adoc index 95320aad5d..95320aad5d 100644 --- a/Documentation/RelNotes/1.7.9.txt +++ b/Documentation/RelNotes/1.7.9.adoc diff --git a/Documentation/RelNotes/1.8.0.1.txt b/Documentation/RelNotes/1.8.0.1.adoc index 1f372fa0b5..1f372fa0b5 100644 --- a/Documentation/RelNotes/1.8.0.1.txt +++ b/Documentation/RelNotes/1.8.0.1.adoc diff --git a/Documentation/RelNotes/1.8.0.2.txt b/Documentation/RelNotes/1.8.0.2.adoc index 8497e051de..8497e051de 100644 --- a/Documentation/RelNotes/1.8.0.2.txt +++ b/Documentation/RelNotes/1.8.0.2.adoc diff --git a/Documentation/RelNotes/1.8.0.3.txt b/Documentation/RelNotes/1.8.0.3.adoc index 92b1e4b363..92b1e4b363 100644 --- a/Documentation/RelNotes/1.8.0.3.txt +++ b/Documentation/RelNotes/1.8.0.3.adoc diff --git a/Documentation/RelNotes/1.8.0.txt b/Documentation/RelNotes/1.8.0.adoc index 63d6e4afa4..63d6e4afa4 100644 --- a/Documentation/RelNotes/1.8.0.txt +++ b/Documentation/RelNotes/1.8.0.adoc diff --git a/Documentation/RelNotes/1.8.1.1.txt b/Documentation/RelNotes/1.8.1.1.adoc index 6cde07ba29..6cde07ba29 100644 --- a/Documentation/RelNotes/1.8.1.1.txt +++ b/Documentation/RelNotes/1.8.1.1.adoc diff --git a/Documentation/RelNotes/1.8.1.2.txt b/Documentation/RelNotes/1.8.1.2.adoc index 5ab7b18906..5ab7b18906 100644 --- a/Documentation/RelNotes/1.8.1.2.txt +++ b/Documentation/RelNotes/1.8.1.2.adoc diff --git a/Documentation/RelNotes/1.8.1.3.txt b/Documentation/RelNotes/1.8.1.3.adoc index 681cb35c0a..681cb35c0a 100644 --- a/Documentation/RelNotes/1.8.1.3.txt +++ b/Documentation/RelNotes/1.8.1.3.adoc diff --git a/Documentation/RelNotes/1.8.1.4.txt b/Documentation/RelNotes/1.8.1.4.adoc index 22af1d1643..22af1d1643 100644 --- a/Documentation/RelNotes/1.8.1.4.txt +++ b/Documentation/RelNotes/1.8.1.4.adoc diff --git a/Documentation/RelNotes/1.8.1.5.txt b/Documentation/RelNotes/1.8.1.5.adoc index efa68aef22..efa68aef22 100644 --- a/Documentation/RelNotes/1.8.1.5.txt +++ b/Documentation/RelNotes/1.8.1.5.adoc diff --git a/Documentation/RelNotes/1.8.1.6.txt b/Documentation/RelNotes/1.8.1.6.adoc index c15cf2e805..c15cf2e805 100644 --- a/Documentation/RelNotes/1.8.1.6.txt +++ b/Documentation/RelNotes/1.8.1.6.adoc diff --git a/Documentation/RelNotes/1.8.1.txt b/Documentation/RelNotes/1.8.1.adoc index d6f9555923..d6f9555923 100644 --- a/Documentation/RelNotes/1.8.1.txt +++ b/Documentation/RelNotes/1.8.1.adoc diff --git a/Documentation/RelNotes/1.8.2.1.txt b/Documentation/RelNotes/1.8.2.1.adoc index 769a6fc06c..769a6fc06c 100644 --- a/Documentation/RelNotes/1.8.2.1.txt +++ b/Documentation/RelNotes/1.8.2.1.adoc diff --git a/Documentation/RelNotes/1.8.2.2.txt b/Documentation/RelNotes/1.8.2.2.adoc index 708df1ae19..708df1ae19 100644 --- a/Documentation/RelNotes/1.8.2.2.txt +++ b/Documentation/RelNotes/1.8.2.2.adoc diff --git a/Documentation/RelNotes/1.8.2.3.txt b/Documentation/RelNotes/1.8.2.3.adoc index 613948251a..613948251a 100644 --- a/Documentation/RelNotes/1.8.2.3.txt +++ b/Documentation/RelNotes/1.8.2.3.adoc diff --git a/Documentation/RelNotes/1.8.2.txt b/Documentation/RelNotes/1.8.2.adoc index fc606ae116..fc606ae116 100644 --- a/Documentation/RelNotes/1.8.2.txt +++ b/Documentation/RelNotes/1.8.2.adoc diff --git a/Documentation/RelNotes/1.8.3.1.txt b/Documentation/RelNotes/1.8.3.1.adoc index 986637b755..986637b755 100644 --- a/Documentation/RelNotes/1.8.3.1.txt +++ b/Documentation/RelNotes/1.8.3.1.adoc diff --git a/Documentation/RelNotes/1.8.3.2.txt b/Documentation/RelNotes/1.8.3.2.adoc index 26ae142c3d..26ae142c3d 100644 --- a/Documentation/RelNotes/1.8.3.2.txt +++ b/Documentation/RelNotes/1.8.3.2.adoc diff --git a/Documentation/RelNotes/1.8.3.3.txt b/Documentation/RelNotes/1.8.3.3.adoc index 9ba4f4da0f..9ba4f4da0f 100644 --- a/Documentation/RelNotes/1.8.3.3.txt +++ b/Documentation/RelNotes/1.8.3.3.adoc diff --git a/Documentation/RelNotes/1.8.3.4.txt b/Documentation/RelNotes/1.8.3.4.adoc index 56f106e262..56f106e262 100644 --- a/Documentation/RelNotes/1.8.3.4.txt +++ b/Documentation/RelNotes/1.8.3.4.adoc diff --git a/Documentation/RelNotes/1.8.3.txt b/Documentation/RelNotes/1.8.3.adoc index ead568e7f1..ead568e7f1 100644 --- a/Documentation/RelNotes/1.8.3.txt +++ b/Documentation/RelNotes/1.8.3.adoc diff --git a/Documentation/RelNotes/1.8.4.1.txt b/Documentation/RelNotes/1.8.4.1.adoc index c257beb114..c257beb114 100644 --- a/Documentation/RelNotes/1.8.4.1.txt +++ b/Documentation/RelNotes/1.8.4.1.adoc diff --git a/Documentation/RelNotes/1.8.4.2.txt b/Documentation/RelNotes/1.8.4.2.adoc index bf6fb1a023..bf6fb1a023 100644 --- a/Documentation/RelNotes/1.8.4.2.txt +++ b/Documentation/RelNotes/1.8.4.2.adoc diff --git a/Documentation/RelNotes/1.8.4.3.txt b/Documentation/RelNotes/1.8.4.3.adoc index 267a1b34b4..267a1b34b4 100644 --- a/Documentation/RelNotes/1.8.4.3.txt +++ b/Documentation/RelNotes/1.8.4.3.adoc diff --git a/Documentation/RelNotes/1.8.4.4.txt b/Documentation/RelNotes/1.8.4.4.adoc index a7c1ce15c0..a7c1ce15c0 100644 --- a/Documentation/RelNotes/1.8.4.4.txt +++ b/Documentation/RelNotes/1.8.4.4.adoc diff --git a/Documentation/RelNotes/1.8.4.5.txt b/Documentation/RelNotes/1.8.4.5.adoc index 215bd1a7a2..215bd1a7a2 100644 --- a/Documentation/RelNotes/1.8.4.5.txt +++ b/Documentation/RelNotes/1.8.4.5.adoc diff --git a/Documentation/RelNotes/1.8.4.txt b/Documentation/RelNotes/1.8.4.adoc index 2e7529928b..2e7529928b 100644 --- a/Documentation/RelNotes/1.8.4.txt +++ b/Documentation/RelNotes/1.8.4.adoc diff --git a/Documentation/RelNotes/1.8.5.1.txt b/Documentation/RelNotes/1.8.5.1.adoc index 7236aaf232..7236aaf232 100644 --- a/Documentation/RelNotes/1.8.5.1.txt +++ b/Documentation/RelNotes/1.8.5.1.adoc diff --git a/Documentation/RelNotes/1.8.5.2.txt b/Documentation/RelNotes/1.8.5.2.adoc index 3ac4984f10..3ac4984f10 100644 --- a/Documentation/RelNotes/1.8.5.2.txt +++ b/Documentation/RelNotes/1.8.5.2.adoc diff --git a/Documentation/RelNotes/1.8.5.3.txt b/Documentation/RelNotes/1.8.5.3.adoc index 3de2dd0f19..3de2dd0f19 100644 --- a/Documentation/RelNotes/1.8.5.3.txt +++ b/Documentation/RelNotes/1.8.5.3.adoc diff --git a/Documentation/RelNotes/1.8.5.4.txt b/Documentation/RelNotes/1.8.5.4.adoc index d18c40389e..d18c40389e 100644 --- a/Documentation/RelNotes/1.8.5.4.txt +++ b/Documentation/RelNotes/1.8.5.4.adoc diff --git a/Documentation/RelNotes/1.8.5.5.txt b/Documentation/RelNotes/1.8.5.5.adoc index 9191ce948f..9191ce948f 100644 --- a/Documentation/RelNotes/1.8.5.5.txt +++ b/Documentation/RelNotes/1.8.5.5.adoc diff --git a/Documentation/RelNotes/1.8.5.6.txt b/Documentation/RelNotes/1.8.5.6.adoc index 92ff92b1e6..92ff92b1e6 100644 --- a/Documentation/RelNotes/1.8.5.6.txt +++ b/Documentation/RelNotes/1.8.5.6.adoc diff --git a/Documentation/RelNotes/1.8.5.txt b/Documentation/RelNotes/1.8.5.adoc index 602df0cac2..602df0cac2 100644 --- a/Documentation/RelNotes/1.8.5.txt +++ b/Documentation/RelNotes/1.8.5.adoc diff --git a/Documentation/RelNotes/1.9.0.txt b/Documentation/RelNotes/1.9.0.adoc index 4e4b88aa5c..4e4b88aa5c 100644 --- a/Documentation/RelNotes/1.9.0.txt +++ b/Documentation/RelNotes/1.9.0.adoc diff --git a/Documentation/RelNotes/1.9.1.txt b/Documentation/RelNotes/1.9.1.adoc index 5b0602053c..5b0602053c 100644 --- a/Documentation/RelNotes/1.9.1.txt +++ b/Documentation/RelNotes/1.9.1.adoc diff --git a/Documentation/RelNotes/1.9.2.txt b/Documentation/RelNotes/1.9.2.adoc index 47a34ca964..47a34ca964 100644 --- a/Documentation/RelNotes/1.9.2.txt +++ b/Documentation/RelNotes/1.9.2.adoc diff --git a/Documentation/RelNotes/1.9.3.txt b/Documentation/RelNotes/1.9.3.adoc index 17b05ca7b5..17b05ca7b5 100644 --- a/Documentation/RelNotes/1.9.3.txt +++ b/Documentation/RelNotes/1.9.3.adoc diff --git a/Documentation/RelNotes/1.9.4.txt b/Documentation/RelNotes/1.9.4.adoc index e1d1835436..e1d1835436 100644 --- a/Documentation/RelNotes/1.9.4.txt +++ b/Documentation/RelNotes/1.9.4.adoc diff --git a/Documentation/RelNotes/1.9.5.txt b/Documentation/RelNotes/1.9.5.adoc index 8d6ac0cf53..8d6ac0cf53 100644 --- a/Documentation/RelNotes/1.9.5.txt +++ b/Documentation/RelNotes/1.9.5.adoc diff --git a/Documentation/RelNotes/2.0.0.txt b/Documentation/RelNotes/2.0.0.adoc index 2617372a0c..2617372a0c 100644 --- a/Documentation/RelNotes/2.0.0.txt +++ b/Documentation/RelNotes/2.0.0.adoc diff --git a/Documentation/RelNotes/2.0.1.txt b/Documentation/RelNotes/2.0.1.adoc index ce5579db3e..ce5579db3e 100644 --- a/Documentation/RelNotes/2.0.1.txt +++ b/Documentation/RelNotes/2.0.1.adoc diff --git a/Documentation/RelNotes/2.0.2.txt b/Documentation/RelNotes/2.0.2.adoc index 8e8321b2ef..8e8321b2ef 100644 --- a/Documentation/RelNotes/2.0.2.txt +++ b/Documentation/RelNotes/2.0.2.adoc diff --git a/Documentation/RelNotes/2.0.3.txt b/Documentation/RelNotes/2.0.3.adoc index 4047b46bbe..4047b46bbe 100644 --- a/Documentation/RelNotes/2.0.3.txt +++ b/Documentation/RelNotes/2.0.3.adoc diff --git a/Documentation/RelNotes/2.0.4.txt b/Documentation/RelNotes/2.0.4.adoc index 7e340921a2..7e340921a2 100644 --- a/Documentation/RelNotes/2.0.4.txt +++ b/Documentation/RelNotes/2.0.4.adoc diff --git a/Documentation/RelNotes/2.0.5.txt b/Documentation/RelNotes/2.0.5.adoc index 3a16f697e8..3a16f697e8 100644 --- a/Documentation/RelNotes/2.0.5.txt +++ b/Documentation/RelNotes/2.0.5.adoc diff --git a/Documentation/RelNotes/2.1.0.txt b/Documentation/RelNotes/2.1.0.adoc index ae4753728e..ae4753728e 100644 --- a/Documentation/RelNotes/2.1.0.txt +++ b/Documentation/RelNotes/2.1.0.adoc diff --git a/Documentation/RelNotes/2.1.1.txt b/Documentation/RelNotes/2.1.1.adoc index 830fc3cc6d..830fc3cc6d 100644 --- a/Documentation/RelNotes/2.1.1.txt +++ b/Documentation/RelNotes/2.1.1.adoc diff --git a/Documentation/RelNotes/2.1.2.txt b/Documentation/RelNotes/2.1.2.adoc index abc3b8928a..abc3b8928a 100644 --- a/Documentation/RelNotes/2.1.2.txt +++ b/Documentation/RelNotes/2.1.2.adoc diff --git a/Documentation/RelNotes/2.1.3.txt b/Documentation/RelNotes/2.1.3.adoc index 0dfb17c4fc..0dfb17c4fc 100644 --- a/Documentation/RelNotes/2.1.3.txt +++ b/Documentation/RelNotes/2.1.3.adoc diff --git a/Documentation/RelNotes/2.1.4.txt b/Documentation/RelNotes/2.1.4.adoc index d16e5f041f..d16e5f041f 100644 --- a/Documentation/RelNotes/2.1.4.txt +++ b/Documentation/RelNotes/2.1.4.adoc diff --git a/Documentation/RelNotes/2.10.0.txt b/Documentation/RelNotes/2.10.0.adoc index 3792b7d03d..3792b7d03d 100644 --- a/Documentation/RelNotes/2.10.0.txt +++ b/Documentation/RelNotes/2.10.0.adoc diff --git a/Documentation/RelNotes/2.10.1.txt b/Documentation/RelNotes/2.10.1.adoc index 70462f7f7e..70462f7f7e 100644 --- a/Documentation/RelNotes/2.10.1.txt +++ b/Documentation/RelNotes/2.10.1.adoc diff --git a/Documentation/RelNotes/2.10.2.txt b/Documentation/RelNotes/2.10.2.adoc index abbd331508..abbd331508 100644 --- a/Documentation/RelNotes/2.10.2.txt +++ b/Documentation/RelNotes/2.10.2.adoc diff --git a/Documentation/RelNotes/2.10.3.txt b/Documentation/RelNotes/2.10.3.adoc index ad6a01bf83..ad6a01bf83 100644 --- a/Documentation/RelNotes/2.10.3.txt +++ b/Documentation/RelNotes/2.10.3.adoc diff --git a/Documentation/RelNotes/2.10.4.txt b/Documentation/RelNotes/2.10.4.adoc index ee8142ad24..ee8142ad24 100644 --- a/Documentation/RelNotes/2.10.4.txt +++ b/Documentation/RelNotes/2.10.4.adoc diff --git a/Documentation/RelNotes/2.10.5.txt b/Documentation/RelNotes/2.10.5.adoc index a498fd6fdc..a498fd6fdc 100644 --- a/Documentation/RelNotes/2.10.5.txt +++ b/Documentation/RelNotes/2.10.5.adoc diff --git a/Documentation/RelNotes/2.11.0.txt b/Documentation/RelNotes/2.11.0.adoc index b7b7dd361e..b7b7dd361e 100644 --- a/Documentation/RelNotes/2.11.0.txt +++ b/Documentation/RelNotes/2.11.0.adoc diff --git a/Documentation/RelNotes/2.11.1.txt b/Documentation/RelNotes/2.11.1.adoc index 7d35cf186d..7d35cf186d 100644 --- a/Documentation/RelNotes/2.11.1.txt +++ b/Documentation/RelNotes/2.11.1.adoc diff --git a/Documentation/RelNotes/2.11.2.txt b/Documentation/RelNotes/2.11.2.adoc index 7428851168..7428851168 100644 --- a/Documentation/RelNotes/2.11.2.txt +++ b/Documentation/RelNotes/2.11.2.adoc diff --git a/Documentation/RelNotes/2.11.3.txt b/Documentation/RelNotes/2.11.3.adoc index 4e3b78d0e8..4e3b78d0e8 100644 --- a/Documentation/RelNotes/2.11.3.txt +++ b/Documentation/RelNotes/2.11.3.adoc diff --git a/Documentation/RelNotes/2.11.4.txt b/Documentation/RelNotes/2.11.4.adoc index ad4da8eb09..ad4da8eb09 100644 --- a/Documentation/RelNotes/2.11.4.txt +++ b/Documentation/RelNotes/2.11.4.adoc diff --git a/Documentation/RelNotes/2.12.0.txt b/Documentation/RelNotes/2.12.0.adoc index d2f6a83614..d2f6a83614 100644 --- a/Documentation/RelNotes/2.12.0.txt +++ b/Documentation/RelNotes/2.12.0.adoc diff --git a/Documentation/RelNotes/2.12.1.txt b/Documentation/RelNotes/2.12.1.adoc index a74f7db747..a74f7db747 100644 --- a/Documentation/RelNotes/2.12.1.txt +++ b/Documentation/RelNotes/2.12.1.adoc diff --git a/Documentation/RelNotes/2.12.2.txt b/Documentation/RelNotes/2.12.2.adoc index 441939709c..441939709c 100644 --- a/Documentation/RelNotes/2.12.2.txt +++ b/Documentation/RelNotes/2.12.2.adoc diff --git a/Documentation/RelNotes/2.12.3.txt b/Documentation/RelNotes/2.12.3.adoc index ebca846d5d..ebca846d5d 100644 --- a/Documentation/RelNotes/2.12.3.txt +++ b/Documentation/RelNotes/2.12.3.adoc diff --git a/Documentation/RelNotes/2.12.4.txt b/Documentation/RelNotes/2.12.4.adoc index 3f56938221..3f56938221 100644 --- a/Documentation/RelNotes/2.12.4.txt +++ b/Documentation/RelNotes/2.12.4.adoc diff --git a/Documentation/RelNotes/2.12.5.txt b/Documentation/RelNotes/2.12.5.adoc index 8fa73cfce7..8fa73cfce7 100644 --- a/Documentation/RelNotes/2.12.5.txt +++ b/Documentation/RelNotes/2.12.5.adoc diff --git a/Documentation/RelNotes/2.13.0.txt b/Documentation/RelNotes/2.13.0.adoc index 2a47b4cb0c..2a47b4cb0c 100644 --- a/Documentation/RelNotes/2.13.0.txt +++ b/Documentation/RelNotes/2.13.0.adoc diff --git a/Documentation/RelNotes/2.13.1.txt b/Documentation/RelNotes/2.13.1.adoc index ed7cd976d9..ed7cd976d9 100644 --- a/Documentation/RelNotes/2.13.1.txt +++ b/Documentation/RelNotes/2.13.1.adoc diff --git a/Documentation/RelNotes/2.13.2.txt b/Documentation/RelNotes/2.13.2.adoc index 8c2b20071e..8c2b20071e 100644 --- a/Documentation/RelNotes/2.13.2.txt +++ b/Documentation/RelNotes/2.13.2.adoc diff --git a/Documentation/RelNotes/2.13.3.txt b/Documentation/RelNotes/2.13.3.adoc index 384e4de265..384e4de265 100644 --- a/Documentation/RelNotes/2.13.3.txt +++ b/Documentation/RelNotes/2.13.3.adoc diff --git a/Documentation/RelNotes/2.13.4.txt b/Documentation/RelNotes/2.13.4.adoc index 9a9f8f9599..9a9f8f9599 100644 --- a/Documentation/RelNotes/2.13.4.txt +++ b/Documentation/RelNotes/2.13.4.adoc diff --git a/Documentation/RelNotes/2.13.5.txt b/Documentation/RelNotes/2.13.5.adoc index 6949fcda78..6949fcda78 100644 --- a/Documentation/RelNotes/2.13.5.txt +++ b/Documentation/RelNotes/2.13.5.adoc diff --git a/Documentation/RelNotes/2.13.6.txt b/Documentation/RelNotes/2.13.6.adoc index afcae9c808..afcae9c808 100644 --- a/Documentation/RelNotes/2.13.6.txt +++ b/Documentation/RelNotes/2.13.6.adoc diff --git a/Documentation/RelNotes/2.13.7.txt b/Documentation/RelNotes/2.13.7.adoc index 09fc01406c..09fc01406c 100644 --- a/Documentation/RelNotes/2.13.7.txt +++ b/Documentation/RelNotes/2.13.7.adoc diff --git a/Documentation/RelNotes/2.14.0.txt b/Documentation/RelNotes/2.14.0.adoc index 2711a2529d..2711a2529d 100644 --- a/Documentation/RelNotes/2.14.0.txt +++ b/Documentation/RelNotes/2.14.0.adoc diff --git a/Documentation/RelNotes/2.14.1.txt b/Documentation/RelNotes/2.14.1.adoc index 9403340f7f..9403340f7f 100644 --- a/Documentation/RelNotes/2.14.1.txt +++ b/Documentation/RelNotes/2.14.1.adoc diff --git a/Documentation/RelNotes/2.14.2.txt b/Documentation/RelNotes/2.14.2.adoc index bec9186ade..bec9186ade 100644 --- a/Documentation/RelNotes/2.14.2.txt +++ b/Documentation/RelNotes/2.14.2.adoc diff --git a/Documentation/RelNotes/2.14.3.txt b/Documentation/RelNotes/2.14.3.adoc index 977c9e857c..977c9e857c 100644 --- a/Documentation/RelNotes/2.14.3.txt +++ b/Documentation/RelNotes/2.14.3.adoc diff --git a/Documentation/RelNotes/2.14.4.txt b/Documentation/RelNotes/2.14.4.adoc index 97755a89d9..97755a89d9 100644 --- a/Documentation/RelNotes/2.14.4.txt +++ b/Documentation/RelNotes/2.14.4.adoc diff --git a/Documentation/RelNotes/2.14.5.txt b/Documentation/RelNotes/2.14.5.adoc index 130645fb29..130645fb29 100644 --- a/Documentation/RelNotes/2.14.5.txt +++ b/Documentation/RelNotes/2.14.5.adoc diff --git a/Documentation/RelNotes/2.14.6.txt b/Documentation/RelNotes/2.14.6.adoc index 72b7af6799..72b7af6799 100644 --- a/Documentation/RelNotes/2.14.6.txt +++ b/Documentation/RelNotes/2.14.6.adoc diff --git a/Documentation/RelNotes/2.15.0.txt b/Documentation/RelNotes/2.15.0.adoc index cdd761bcc2..cdd761bcc2 100644 --- a/Documentation/RelNotes/2.15.0.txt +++ b/Documentation/RelNotes/2.15.0.adoc diff --git a/Documentation/RelNotes/2.15.1.txt b/Documentation/RelNotes/2.15.1.adoc index ec06704e63..ec06704e63 100644 --- a/Documentation/RelNotes/2.15.1.txt +++ b/Documentation/RelNotes/2.15.1.adoc diff --git a/Documentation/RelNotes/2.15.2.txt b/Documentation/RelNotes/2.15.2.adoc index b480e56b68..b480e56b68 100644 --- a/Documentation/RelNotes/2.15.2.txt +++ b/Documentation/RelNotes/2.15.2.adoc diff --git a/Documentation/RelNotes/2.15.3.txt b/Documentation/RelNotes/2.15.3.adoc index fd2e6f8df7..fd2e6f8df7 100644 --- a/Documentation/RelNotes/2.15.3.txt +++ b/Documentation/RelNotes/2.15.3.adoc diff --git a/Documentation/RelNotes/2.15.4.txt b/Documentation/RelNotes/2.15.4.adoc index dc241cba34..dc241cba34 100644 --- a/Documentation/RelNotes/2.15.4.txt +++ b/Documentation/RelNotes/2.15.4.adoc diff --git a/Documentation/RelNotes/2.16.0.txt b/Documentation/RelNotes/2.16.0.adoc index b474781ed8..b474781ed8 100644 --- a/Documentation/RelNotes/2.16.0.txt +++ b/Documentation/RelNotes/2.16.0.adoc diff --git a/Documentation/RelNotes/2.16.1.txt b/Documentation/RelNotes/2.16.1.adoc index 66e64361fd..66e64361fd 100644 --- a/Documentation/RelNotes/2.16.1.txt +++ b/Documentation/RelNotes/2.16.1.adoc diff --git a/Documentation/RelNotes/2.16.2.txt b/Documentation/RelNotes/2.16.2.adoc index a216466d3d..a216466d3d 100644 --- a/Documentation/RelNotes/2.16.2.txt +++ b/Documentation/RelNotes/2.16.2.adoc diff --git a/Documentation/RelNotes/2.16.3.txt b/Documentation/RelNotes/2.16.3.adoc index f0121a8f2d..f0121a8f2d 100644 --- a/Documentation/RelNotes/2.16.3.txt +++ b/Documentation/RelNotes/2.16.3.adoc diff --git a/Documentation/RelNotes/2.16.4.txt b/Documentation/RelNotes/2.16.4.adoc index 6be538ba30..6be538ba30 100644 --- a/Documentation/RelNotes/2.16.4.txt +++ b/Documentation/RelNotes/2.16.4.adoc diff --git a/Documentation/RelNotes/2.16.5.txt b/Documentation/RelNotes/2.16.5.adoc index cb8ee02a9a..cb8ee02a9a 100644 --- a/Documentation/RelNotes/2.16.5.txt +++ b/Documentation/RelNotes/2.16.5.adoc diff --git a/Documentation/RelNotes/2.16.6.txt b/Documentation/RelNotes/2.16.6.adoc index 438306e60b..438306e60b 100644 --- a/Documentation/RelNotes/2.16.6.txt +++ b/Documentation/RelNotes/2.16.6.adoc diff --git a/Documentation/RelNotes/2.17.0.txt b/Documentation/RelNotes/2.17.0.adoc index 8b17c26033..8b17c26033 100644 --- a/Documentation/RelNotes/2.17.0.txt +++ b/Documentation/RelNotes/2.17.0.adoc diff --git a/Documentation/RelNotes/2.17.1.txt b/Documentation/RelNotes/2.17.1.adoc index e01384fe8e..e01384fe8e 100644 --- a/Documentation/RelNotes/2.17.1.txt +++ b/Documentation/RelNotes/2.17.1.adoc diff --git a/Documentation/RelNotes/2.17.2.txt b/Documentation/RelNotes/2.17.2.adoc index ef021be870..ef021be870 100644 --- a/Documentation/RelNotes/2.17.2.txt +++ b/Documentation/RelNotes/2.17.2.adoc diff --git a/Documentation/RelNotes/2.17.3.txt b/Documentation/RelNotes/2.17.3.adoc index 5a46c94271..5a46c94271 100644 --- a/Documentation/RelNotes/2.17.3.txt +++ b/Documentation/RelNotes/2.17.3.adoc diff --git a/Documentation/RelNotes/2.17.4.txt b/Documentation/RelNotes/2.17.4.adoc index 7d794ca01a..7d794ca01a 100644 --- a/Documentation/RelNotes/2.17.4.txt +++ b/Documentation/RelNotes/2.17.4.adoc diff --git a/Documentation/RelNotes/2.17.5.txt b/Documentation/RelNotes/2.17.5.adoc index 2abb821a73..2abb821a73 100644 --- a/Documentation/RelNotes/2.17.5.txt +++ b/Documentation/RelNotes/2.17.5.adoc diff --git a/Documentation/RelNotes/2.17.6.txt b/Documentation/RelNotes/2.17.6.adoc index 2f181e8064..2f181e8064 100644 --- a/Documentation/RelNotes/2.17.6.txt +++ b/Documentation/RelNotes/2.17.6.adoc diff --git a/Documentation/RelNotes/2.18.0.txt b/Documentation/RelNotes/2.18.0.adoc index 6c8a0e97c1..6c8a0e97c1 100644 --- a/Documentation/RelNotes/2.18.0.txt +++ b/Documentation/RelNotes/2.18.0.adoc diff --git a/Documentation/RelNotes/2.18.1.txt b/Documentation/RelNotes/2.18.1.adoc index 2098cdd776..2098cdd776 100644 --- a/Documentation/RelNotes/2.18.1.txt +++ b/Documentation/RelNotes/2.18.1.adoc diff --git a/Documentation/RelNotes/2.18.2.txt b/Documentation/RelNotes/2.18.2.adoc index 98b168aade..98b168aade 100644 --- a/Documentation/RelNotes/2.18.2.txt +++ b/Documentation/RelNotes/2.18.2.adoc diff --git a/Documentation/RelNotes/2.18.3.txt b/Documentation/RelNotes/2.18.3.adoc index 25143f0cec..25143f0cec 100644 --- a/Documentation/RelNotes/2.18.3.txt +++ b/Documentation/RelNotes/2.18.3.adoc diff --git a/Documentation/RelNotes/2.18.4.txt b/Documentation/RelNotes/2.18.4.adoc index e8ef858a00..e8ef858a00 100644 --- a/Documentation/RelNotes/2.18.4.txt +++ b/Documentation/RelNotes/2.18.4.adoc diff --git a/Documentation/RelNotes/2.18.5.txt b/Documentation/RelNotes/2.18.5.adoc index dfb1de4ceb..dfb1de4ceb 100644 --- a/Documentation/RelNotes/2.18.5.txt +++ b/Documentation/RelNotes/2.18.5.adoc diff --git a/Documentation/RelNotes/2.19.0.txt b/Documentation/RelNotes/2.19.0.adoc index 891c79b9cb..891c79b9cb 100644 --- a/Documentation/RelNotes/2.19.0.txt +++ b/Documentation/RelNotes/2.19.0.adoc diff --git a/Documentation/RelNotes/2.19.1.txt b/Documentation/RelNotes/2.19.1.adoc index da7672674e..da7672674e 100644 --- a/Documentation/RelNotes/2.19.1.txt +++ b/Documentation/RelNotes/2.19.1.adoc diff --git a/Documentation/RelNotes/2.19.2.txt b/Documentation/RelNotes/2.19.2.adoc index 759e6ca957..759e6ca957 100644 --- a/Documentation/RelNotes/2.19.2.txt +++ b/Documentation/RelNotes/2.19.2.adoc diff --git a/Documentation/RelNotes/2.19.3.txt b/Documentation/RelNotes/2.19.3.adoc index 92d7f89de6..92d7f89de6 100644 --- a/Documentation/RelNotes/2.19.3.txt +++ b/Documentation/RelNotes/2.19.3.adoc diff --git a/Documentation/RelNotes/2.19.4.txt b/Documentation/RelNotes/2.19.4.adoc index 35d0ae561b..35d0ae561b 100644 --- a/Documentation/RelNotes/2.19.4.txt +++ b/Documentation/RelNotes/2.19.4.adoc diff --git a/Documentation/RelNotes/2.19.5.txt b/Documentation/RelNotes/2.19.5.adoc index 18a4dcbfd6..18a4dcbfd6 100644 --- a/Documentation/RelNotes/2.19.5.txt +++ b/Documentation/RelNotes/2.19.5.adoc diff --git a/Documentation/RelNotes/2.19.6.txt b/Documentation/RelNotes/2.19.6.adoc index bcca6cd258..bcca6cd258 100644 --- a/Documentation/RelNotes/2.19.6.txt +++ b/Documentation/RelNotes/2.19.6.adoc diff --git a/Documentation/RelNotes/2.2.0.txt b/Documentation/RelNotes/2.2.0.adoc index e98ecbcff6..e98ecbcff6 100644 --- a/Documentation/RelNotes/2.2.0.txt +++ b/Documentation/RelNotes/2.2.0.adoc diff --git a/Documentation/RelNotes/2.2.1.txt b/Documentation/RelNotes/2.2.1.adoc index d5a3cd9e73..d5a3cd9e73 100644 --- a/Documentation/RelNotes/2.2.1.txt +++ b/Documentation/RelNotes/2.2.1.adoc diff --git a/Documentation/RelNotes/2.2.2.txt b/Documentation/RelNotes/2.2.2.adoc index b19a35d94f..b19a35d94f 100644 --- a/Documentation/RelNotes/2.2.2.txt +++ b/Documentation/RelNotes/2.2.2.adoc diff --git a/Documentation/RelNotes/2.2.3.txt b/Documentation/RelNotes/2.2.3.adoc index 5bfffa4106..5bfffa4106 100644 --- a/Documentation/RelNotes/2.2.3.txt +++ b/Documentation/RelNotes/2.2.3.adoc diff --git a/Documentation/RelNotes/2.20.0.txt b/Documentation/RelNotes/2.20.0.adoc index 3dd7e6e1fc..3dd7e6e1fc 100644 --- a/Documentation/RelNotes/2.20.0.txt +++ b/Documentation/RelNotes/2.20.0.adoc diff --git a/Documentation/RelNotes/2.20.1.txt b/Documentation/RelNotes/2.20.1.adoc index dcba888dba..dcba888dba 100644 --- a/Documentation/RelNotes/2.20.1.txt +++ b/Documentation/RelNotes/2.20.1.adoc diff --git a/Documentation/RelNotes/2.20.2.txt b/Documentation/RelNotes/2.20.2.adoc index 8e680cb9fb..8e680cb9fb 100644 --- a/Documentation/RelNotes/2.20.2.txt +++ b/Documentation/RelNotes/2.20.2.adoc diff --git a/Documentation/RelNotes/2.20.3.txt b/Documentation/RelNotes/2.20.3.adoc index f6eccd103b..f6eccd103b 100644 --- a/Documentation/RelNotes/2.20.3.txt +++ b/Documentation/RelNotes/2.20.3.adoc diff --git a/Documentation/RelNotes/2.20.4.txt b/Documentation/RelNotes/2.20.4.adoc index 5a9e24e470..5a9e24e470 100644 --- a/Documentation/RelNotes/2.20.4.txt +++ b/Documentation/RelNotes/2.20.4.adoc diff --git a/Documentation/RelNotes/2.20.5.txt b/Documentation/RelNotes/2.20.5.adoc index 1dfb784ded..1dfb784ded 100644 --- a/Documentation/RelNotes/2.20.5.txt +++ b/Documentation/RelNotes/2.20.5.adoc diff --git a/Documentation/RelNotes/2.21.0.txt b/Documentation/RelNotes/2.21.0.adoc index 7a49deddf3..7a49deddf3 100644 --- a/Documentation/RelNotes/2.21.0.txt +++ b/Documentation/RelNotes/2.21.0.adoc diff --git a/Documentation/RelNotes/2.21.1.txt b/Documentation/RelNotes/2.21.1.adoc index b7594151e4..b7594151e4 100644 --- a/Documentation/RelNotes/2.21.1.txt +++ b/Documentation/RelNotes/2.21.1.adoc diff --git a/Documentation/RelNotes/2.21.2.txt b/Documentation/RelNotes/2.21.2.adoc index a0fb83bb53..a0fb83bb53 100644 --- a/Documentation/RelNotes/2.21.2.txt +++ b/Documentation/RelNotes/2.21.2.adoc diff --git a/Documentation/RelNotes/2.21.3.txt b/Documentation/RelNotes/2.21.3.adoc index 2ca0aa5c62..2ca0aa5c62 100644 --- a/Documentation/RelNotes/2.21.3.txt +++ b/Documentation/RelNotes/2.21.3.adoc diff --git a/Documentation/RelNotes/2.21.4.txt b/Documentation/RelNotes/2.21.4.adoc index 0089dd6702..0089dd6702 100644 --- a/Documentation/RelNotes/2.21.4.txt +++ b/Documentation/RelNotes/2.21.4.adoc diff --git a/Documentation/RelNotes/2.22.0.txt b/Documentation/RelNotes/2.22.0.adoc index 91e6ae9887..91e6ae9887 100644 --- a/Documentation/RelNotes/2.22.0.txt +++ b/Documentation/RelNotes/2.22.0.adoc diff --git a/Documentation/RelNotes/2.22.1.txt b/Documentation/RelNotes/2.22.1.adoc index 432762f270..432762f270 100644 --- a/Documentation/RelNotes/2.22.1.txt +++ b/Documentation/RelNotes/2.22.1.adoc diff --git a/Documentation/RelNotes/2.22.2.txt b/Documentation/RelNotes/2.22.2.adoc index 940a23f0d9..940a23f0d9 100644 --- a/Documentation/RelNotes/2.22.2.txt +++ b/Documentation/RelNotes/2.22.2.adoc diff --git a/Documentation/RelNotes/2.22.3.txt b/Documentation/RelNotes/2.22.3.adoc index 57296f6d17..57296f6d17 100644 --- a/Documentation/RelNotes/2.22.3.txt +++ b/Documentation/RelNotes/2.22.3.adoc diff --git a/Documentation/RelNotes/2.22.4.txt b/Documentation/RelNotes/2.22.4.adoc index 8b5f3e3f37..8b5f3e3f37 100644 --- a/Documentation/RelNotes/2.22.4.txt +++ b/Documentation/RelNotes/2.22.4.adoc diff --git a/Documentation/RelNotes/2.22.5.txt b/Documentation/RelNotes/2.22.5.adoc index 6b280d9321..6b280d9321 100644 --- a/Documentation/RelNotes/2.22.5.txt +++ b/Documentation/RelNotes/2.22.5.adoc diff --git a/Documentation/RelNotes/2.23.0.txt b/Documentation/RelNotes/2.23.0.adoc index e3c4e78265..e3c4e78265 100644 --- a/Documentation/RelNotes/2.23.0.txt +++ b/Documentation/RelNotes/2.23.0.adoc diff --git a/Documentation/RelNotes/2.23.1.txt b/Documentation/RelNotes/2.23.1.adoc index 2083b492ce..2083b492ce 100644 --- a/Documentation/RelNotes/2.23.1.txt +++ b/Documentation/RelNotes/2.23.1.adoc diff --git a/Documentation/RelNotes/2.23.2.txt b/Documentation/RelNotes/2.23.2.adoc index b697cbe0e3..b697cbe0e3 100644 --- a/Documentation/RelNotes/2.23.2.txt +++ b/Documentation/RelNotes/2.23.2.adoc diff --git a/Documentation/RelNotes/2.23.3.txt b/Documentation/RelNotes/2.23.3.adoc index 2e35490137..2e35490137 100644 --- a/Documentation/RelNotes/2.23.3.txt +++ b/Documentation/RelNotes/2.23.3.adoc diff --git a/Documentation/RelNotes/2.23.4.txt b/Documentation/RelNotes/2.23.4.adoc index 6e5424d0da..6e5424d0da 100644 --- a/Documentation/RelNotes/2.23.4.txt +++ b/Documentation/RelNotes/2.23.4.adoc diff --git a/Documentation/RelNotes/2.24.0.txt b/Documentation/RelNotes/2.24.0.adoc index bde154124c..bde154124c 100644 --- a/Documentation/RelNotes/2.24.0.txt +++ b/Documentation/RelNotes/2.24.0.adoc diff --git a/Documentation/RelNotes/2.24.1.txt b/Documentation/RelNotes/2.24.1.adoc index 18104850fe..18104850fe 100644 --- a/Documentation/RelNotes/2.24.1.txt +++ b/Documentation/RelNotes/2.24.1.adoc diff --git a/Documentation/RelNotes/2.24.2.txt b/Documentation/RelNotes/2.24.2.adoc index 0049f65503..0049f65503 100644 --- a/Documentation/RelNotes/2.24.2.txt +++ b/Documentation/RelNotes/2.24.2.adoc diff --git a/Documentation/RelNotes/2.24.3.txt b/Documentation/RelNotes/2.24.3.adoc index 5302e0f73b..5302e0f73b 100644 --- a/Documentation/RelNotes/2.24.3.txt +++ b/Documentation/RelNotes/2.24.3.adoc diff --git a/Documentation/RelNotes/2.24.4.txt b/Documentation/RelNotes/2.24.4.adoc index 4e216eec2a..4e216eec2a 100644 --- a/Documentation/RelNotes/2.24.4.txt +++ b/Documentation/RelNotes/2.24.4.adoc diff --git a/Documentation/RelNotes/2.25.0.txt b/Documentation/RelNotes/2.25.0.adoc index 91ceb34927..91ceb34927 100644 --- a/Documentation/RelNotes/2.25.0.txt +++ b/Documentation/RelNotes/2.25.0.adoc diff --git a/Documentation/RelNotes/2.25.1.txt b/Documentation/RelNotes/2.25.1.adoc index cd869b02bb..cd869b02bb 100644 --- a/Documentation/RelNotes/2.25.1.txt +++ b/Documentation/RelNotes/2.25.1.adoc diff --git a/Documentation/RelNotes/2.25.2.txt b/Documentation/RelNotes/2.25.2.adoc index 303c53a17f..303c53a17f 100644 --- a/Documentation/RelNotes/2.25.2.txt +++ b/Documentation/RelNotes/2.25.2.adoc diff --git a/Documentation/RelNotes/2.25.3.txt b/Documentation/RelNotes/2.25.3.adoc index 15f7f21f10..15f7f21f10 100644 --- a/Documentation/RelNotes/2.25.3.txt +++ b/Documentation/RelNotes/2.25.3.adoc diff --git a/Documentation/RelNotes/2.25.4.txt b/Documentation/RelNotes/2.25.4.adoc index 0dbb5daeec..0dbb5daeec 100644 --- a/Documentation/RelNotes/2.25.4.txt +++ b/Documentation/RelNotes/2.25.4.adoc diff --git a/Documentation/RelNotes/2.25.5.txt b/Documentation/RelNotes/2.25.5.adoc index fcb9566b15..fcb9566b15 100644 --- a/Documentation/RelNotes/2.25.5.txt +++ b/Documentation/RelNotes/2.25.5.adoc diff --git a/Documentation/RelNotes/2.26.0.txt b/Documentation/RelNotes/2.26.0.adoc index 3a7a734c26..3a7a734c26 100644 --- a/Documentation/RelNotes/2.26.0.txt +++ b/Documentation/RelNotes/2.26.0.adoc diff --git a/Documentation/RelNotes/2.26.1.txt b/Documentation/RelNotes/2.26.1.adoc index 1b4ecb3fdc..1b4ecb3fdc 100644 --- a/Documentation/RelNotes/2.26.1.txt +++ b/Documentation/RelNotes/2.26.1.adoc diff --git a/Documentation/RelNotes/2.26.2.txt b/Documentation/RelNotes/2.26.2.adoc index d434d0c695..d434d0c695 100644 --- a/Documentation/RelNotes/2.26.2.txt +++ b/Documentation/RelNotes/2.26.2.adoc diff --git a/Documentation/RelNotes/2.26.3.txt b/Documentation/RelNotes/2.26.3.adoc index 4111c38f0a..4111c38f0a 100644 --- a/Documentation/RelNotes/2.26.3.txt +++ b/Documentation/RelNotes/2.26.3.adoc diff --git a/Documentation/RelNotes/2.27.0.txt b/Documentation/RelNotes/2.27.0.adoc index 15518d06c1..15518d06c1 100644 --- a/Documentation/RelNotes/2.27.0.txt +++ b/Documentation/RelNotes/2.27.0.adoc diff --git a/Documentation/RelNotes/2.27.1.txt b/Documentation/RelNotes/2.27.1.adoc index a1e08a9f72..a1e08a9f72 100644 --- a/Documentation/RelNotes/2.27.1.txt +++ b/Documentation/RelNotes/2.27.1.adoc diff --git a/Documentation/RelNotes/2.28.0.txt b/Documentation/RelNotes/2.28.0.adoc index 6baf781380..6baf781380 100644 --- a/Documentation/RelNotes/2.28.0.txt +++ b/Documentation/RelNotes/2.28.0.adoc diff --git a/Documentation/RelNotes/2.28.1.txt b/Documentation/RelNotes/2.28.1.adoc index 8484c8297c..8484c8297c 100644 --- a/Documentation/RelNotes/2.28.1.txt +++ b/Documentation/RelNotes/2.28.1.adoc diff --git a/Documentation/RelNotes/2.29.0.txt b/Documentation/RelNotes/2.29.0.adoc index 1f41302ebb..1f41302ebb 100644 --- a/Documentation/RelNotes/2.29.0.txt +++ b/Documentation/RelNotes/2.29.0.adoc diff --git a/Documentation/RelNotes/2.29.1.txt b/Documentation/RelNotes/2.29.1.adoc index 295ee2135f..295ee2135f 100644 --- a/Documentation/RelNotes/2.29.1.txt +++ b/Documentation/RelNotes/2.29.1.adoc diff --git a/Documentation/RelNotes/2.29.2.txt b/Documentation/RelNotes/2.29.2.adoc index 632b5b580a..632b5b580a 100644 --- a/Documentation/RelNotes/2.29.2.txt +++ b/Documentation/RelNotes/2.29.2.adoc diff --git a/Documentation/RelNotes/2.29.3.txt b/Documentation/RelNotes/2.29.3.adoc index e10eedb35a..e10eedb35a 100644 --- a/Documentation/RelNotes/2.29.3.txt +++ b/Documentation/RelNotes/2.29.3.adoc diff --git a/Documentation/RelNotes/2.3.0.txt b/Documentation/RelNotes/2.3.0.adoc index e3c639c840..e3c639c840 100644 --- a/Documentation/RelNotes/2.3.0.txt +++ b/Documentation/RelNotes/2.3.0.adoc diff --git a/Documentation/RelNotes/2.3.1.txt b/Documentation/RelNotes/2.3.1.adoc index cf96186288..cf96186288 100644 --- a/Documentation/RelNotes/2.3.1.txt +++ b/Documentation/RelNotes/2.3.1.adoc diff --git a/Documentation/RelNotes/2.3.10.txt b/Documentation/RelNotes/2.3.10.adoc index 20c2d2cacc..20c2d2cacc 100644 --- a/Documentation/RelNotes/2.3.10.txt +++ b/Documentation/RelNotes/2.3.10.adoc diff --git a/Documentation/RelNotes/2.3.2.txt b/Documentation/RelNotes/2.3.2.adoc index 93462e45c2..93462e45c2 100644 --- a/Documentation/RelNotes/2.3.2.txt +++ b/Documentation/RelNotes/2.3.2.adoc diff --git a/Documentation/RelNotes/2.3.3.txt b/Documentation/RelNotes/2.3.3.adoc index 850dc68ede..850dc68ede 100644 --- a/Documentation/RelNotes/2.3.3.txt +++ b/Documentation/RelNotes/2.3.3.adoc diff --git a/Documentation/RelNotes/2.3.4.txt b/Documentation/RelNotes/2.3.4.adoc index 094c7b853b..094c7b853b 100644 --- a/Documentation/RelNotes/2.3.4.txt +++ b/Documentation/RelNotes/2.3.4.adoc diff --git a/Documentation/RelNotes/2.3.5.txt b/Documentation/RelNotes/2.3.5.adoc index 5b309db689..5b309db689 100644 --- a/Documentation/RelNotes/2.3.5.txt +++ b/Documentation/RelNotes/2.3.5.adoc diff --git a/Documentation/RelNotes/2.3.6.txt b/Documentation/RelNotes/2.3.6.adoc index 432f770ef3..432f770ef3 100644 --- a/Documentation/RelNotes/2.3.6.txt +++ b/Documentation/RelNotes/2.3.6.adoc diff --git a/Documentation/RelNotes/2.3.7.txt b/Documentation/RelNotes/2.3.7.adoc index 5769184081..5769184081 100644 --- a/Documentation/RelNotes/2.3.7.txt +++ b/Documentation/RelNotes/2.3.7.adoc diff --git a/Documentation/RelNotes/2.3.8.txt b/Documentation/RelNotes/2.3.8.adoc index 0b67268a96..0b67268a96 100644 --- a/Documentation/RelNotes/2.3.8.txt +++ b/Documentation/RelNotes/2.3.8.adoc diff --git a/Documentation/RelNotes/2.3.9.txt b/Documentation/RelNotes/2.3.9.adoc index 1a2ad3235a..1a2ad3235a 100644 --- a/Documentation/RelNotes/2.3.9.txt +++ b/Documentation/RelNotes/2.3.9.adoc diff --git a/Documentation/RelNotes/2.30.0.txt b/Documentation/RelNotes/2.30.0.adoc index c2f1dc7b06..c2f1dc7b06 100644 --- a/Documentation/RelNotes/2.30.0.txt +++ b/Documentation/RelNotes/2.30.0.adoc diff --git a/Documentation/RelNotes/2.30.1.txt b/Documentation/RelNotes/2.30.1.adoc index 249ef1492f..249ef1492f 100644 --- a/Documentation/RelNotes/2.30.1.txt +++ b/Documentation/RelNotes/2.30.1.adoc diff --git a/Documentation/RelNotes/2.30.2.txt b/Documentation/RelNotes/2.30.2.adoc index bada398501..bada398501 100644 --- a/Documentation/RelNotes/2.30.2.txt +++ b/Documentation/RelNotes/2.30.2.adoc diff --git a/Documentation/RelNotes/2.30.3.txt b/Documentation/RelNotes/2.30.3.adoc index 31b2a4daa6..31b2a4daa6 100644 --- a/Documentation/RelNotes/2.30.3.txt +++ b/Documentation/RelNotes/2.30.3.adoc diff --git a/Documentation/RelNotes/2.30.4.txt b/Documentation/RelNotes/2.30.4.adoc index 4eedb74b16..4eedb74b16 100644 --- a/Documentation/RelNotes/2.30.4.txt +++ b/Documentation/RelNotes/2.30.4.adoc diff --git a/Documentation/RelNotes/2.30.5.txt b/Documentation/RelNotes/2.30.5.adoc index 5191cab3ae..5191cab3ae 100644 --- a/Documentation/RelNotes/2.30.5.txt +++ b/Documentation/RelNotes/2.30.5.adoc diff --git a/Documentation/RelNotes/2.30.6.txt b/Documentation/RelNotes/2.30.6.adoc index d649071b79..d649071b79 100644 --- a/Documentation/RelNotes/2.30.6.txt +++ b/Documentation/RelNotes/2.30.6.adoc diff --git a/Documentation/RelNotes/2.30.7.txt b/Documentation/RelNotes/2.30.7.adoc index 285beed232..285beed232 100644 --- a/Documentation/RelNotes/2.30.7.txt +++ b/Documentation/RelNotes/2.30.7.adoc diff --git a/Documentation/RelNotes/2.30.8.txt b/Documentation/RelNotes/2.30.8.adoc index 5ed3efbd6a..5ed3efbd6a 100644 --- a/Documentation/RelNotes/2.30.8.txt +++ b/Documentation/RelNotes/2.30.8.adoc diff --git a/Documentation/RelNotes/2.30.9.txt b/Documentation/RelNotes/2.30.9.adoc index 708d626ce6..708d626ce6 100644 --- a/Documentation/RelNotes/2.30.9.txt +++ b/Documentation/RelNotes/2.30.9.adoc diff --git a/Documentation/RelNotes/2.31.0.txt b/Documentation/RelNotes/2.31.0.adoc index cf0c7d8d40..cf0c7d8d40 100644 --- a/Documentation/RelNotes/2.31.0.txt +++ b/Documentation/RelNotes/2.31.0.adoc diff --git a/Documentation/RelNotes/2.31.1.txt b/Documentation/RelNotes/2.31.1.adoc index f9b06b8e1b..f9b06b8e1b 100644 --- a/Documentation/RelNotes/2.31.1.txt +++ b/Documentation/RelNotes/2.31.1.adoc diff --git a/Documentation/RelNotes/2.31.2.txt b/Documentation/RelNotes/2.31.2.adoc index aa13a5b022..aa13a5b022 100644 --- a/Documentation/RelNotes/2.31.2.txt +++ b/Documentation/RelNotes/2.31.2.adoc diff --git a/Documentation/RelNotes/2.31.3.txt b/Documentation/RelNotes/2.31.3.adoc index ca143abad0..ca143abad0 100644 --- a/Documentation/RelNotes/2.31.3.txt +++ b/Documentation/RelNotes/2.31.3.adoc diff --git a/Documentation/RelNotes/2.31.4.txt b/Documentation/RelNotes/2.31.4.adoc index 97a91fd07a..97a91fd07a 100644 --- a/Documentation/RelNotes/2.31.4.txt +++ b/Documentation/RelNotes/2.31.4.adoc diff --git a/Documentation/RelNotes/2.31.5.txt b/Documentation/RelNotes/2.31.5.adoc index 0d87e6e03f..0d87e6e03f 100644 --- a/Documentation/RelNotes/2.31.5.txt +++ b/Documentation/RelNotes/2.31.5.adoc diff --git a/Documentation/RelNotes/2.31.6.txt b/Documentation/RelNotes/2.31.6.adoc index 425a51875a..425a51875a 100644 --- a/Documentation/RelNotes/2.31.6.txt +++ b/Documentation/RelNotes/2.31.6.adoc diff --git a/Documentation/RelNotes/2.31.7.txt b/Documentation/RelNotes/2.31.7.adoc index dd44d5bc62..dd44d5bc62 100644 --- a/Documentation/RelNotes/2.31.7.txt +++ b/Documentation/RelNotes/2.31.7.adoc diff --git a/Documentation/RelNotes/2.31.8.txt b/Documentation/RelNotes/2.31.8.adoc index 0aa3080780..0aa3080780 100644 --- a/Documentation/RelNotes/2.31.8.txt +++ b/Documentation/RelNotes/2.31.8.adoc diff --git a/Documentation/RelNotes/2.32.0.txt b/Documentation/RelNotes/2.32.0.adoc index 87d56fa1aa..87d56fa1aa 100644 --- a/Documentation/RelNotes/2.32.0.txt +++ b/Documentation/RelNotes/2.32.0.adoc diff --git a/Documentation/RelNotes/2.32.1.txt b/Documentation/RelNotes/2.32.1.adoc index 7dcca13b92..7dcca13b92 100644 --- a/Documentation/RelNotes/2.32.1.txt +++ b/Documentation/RelNotes/2.32.1.adoc diff --git a/Documentation/RelNotes/2.32.2.txt b/Documentation/RelNotes/2.32.2.adoc index cf49695f2f..cf49695f2f 100644 --- a/Documentation/RelNotes/2.32.2.txt +++ b/Documentation/RelNotes/2.32.2.adoc diff --git a/Documentation/RelNotes/2.32.3.txt b/Documentation/RelNotes/2.32.3.adoc index 583fabe684..583fabe684 100644 --- a/Documentation/RelNotes/2.32.3.txt +++ b/Documentation/RelNotes/2.32.3.adoc diff --git a/Documentation/RelNotes/2.32.4.txt b/Documentation/RelNotes/2.32.4.adoc index 76c67b209e..76c67b209e 100644 --- a/Documentation/RelNotes/2.32.4.txt +++ b/Documentation/RelNotes/2.32.4.adoc diff --git a/Documentation/RelNotes/2.32.5.txt b/Documentation/RelNotes/2.32.5.adoc index a8cad1a05b..a8cad1a05b 100644 --- a/Documentation/RelNotes/2.32.5.txt +++ b/Documentation/RelNotes/2.32.5.adoc diff --git a/Documentation/RelNotes/2.32.6.txt b/Documentation/RelNotes/2.32.6.adoc index fd659612e3..fd659612e3 100644 --- a/Documentation/RelNotes/2.32.6.txt +++ b/Documentation/RelNotes/2.32.6.adoc diff --git a/Documentation/RelNotes/2.32.7.txt b/Documentation/RelNotes/2.32.7.adoc index 7bb35388b5..7bb35388b5 100644 --- a/Documentation/RelNotes/2.32.7.txt +++ b/Documentation/RelNotes/2.32.7.adoc diff --git a/Documentation/RelNotes/2.33.0.txt b/Documentation/RelNotes/2.33.0.adoc index 893c18bfdd..893c18bfdd 100644 --- a/Documentation/RelNotes/2.33.0.txt +++ b/Documentation/RelNotes/2.33.0.adoc diff --git a/Documentation/RelNotes/2.33.1.txt b/Documentation/RelNotes/2.33.1.adoc index b71738e654..b71738e654 100644 --- a/Documentation/RelNotes/2.33.1.txt +++ b/Documentation/RelNotes/2.33.1.adoc diff --git a/Documentation/RelNotes/2.33.2.txt b/Documentation/RelNotes/2.33.2.adoc index e504489d61..e504489d61 100644 --- a/Documentation/RelNotes/2.33.2.txt +++ b/Documentation/RelNotes/2.33.2.adoc diff --git a/Documentation/RelNotes/2.33.3.txt b/Documentation/RelNotes/2.33.3.adoc index e2bada12a1..e2bada12a1 100644 --- a/Documentation/RelNotes/2.33.3.txt +++ b/Documentation/RelNotes/2.33.3.adoc diff --git a/Documentation/RelNotes/2.33.4.txt b/Documentation/RelNotes/2.33.4.adoc index a145cc25de..a145cc25de 100644 --- a/Documentation/RelNotes/2.33.4.txt +++ b/Documentation/RelNotes/2.33.4.adoc diff --git a/Documentation/RelNotes/2.33.5.txt b/Documentation/RelNotes/2.33.5.adoc index a63652602b..a63652602b 100644 --- a/Documentation/RelNotes/2.33.5.txt +++ b/Documentation/RelNotes/2.33.5.adoc diff --git a/Documentation/RelNotes/2.33.6.txt b/Documentation/RelNotes/2.33.6.adoc index b63e4e6256..b63e4e6256 100644 --- a/Documentation/RelNotes/2.33.6.txt +++ b/Documentation/RelNotes/2.33.6.adoc diff --git a/Documentation/RelNotes/2.33.7.txt b/Documentation/RelNotes/2.33.7.adoc index 078a837cb4..078a837cb4 100644 --- a/Documentation/RelNotes/2.33.7.txt +++ b/Documentation/RelNotes/2.33.7.adoc diff --git a/Documentation/RelNotes/2.33.8.txt b/Documentation/RelNotes/2.33.8.adoc index d8cf4c7f3a..d8cf4c7f3a 100644 --- a/Documentation/RelNotes/2.33.8.txt +++ b/Documentation/RelNotes/2.33.8.adoc diff --git a/Documentation/RelNotes/2.34.0.txt b/Documentation/RelNotes/2.34.0.adoc index 75d4fdfde7..75d4fdfde7 100644 --- a/Documentation/RelNotes/2.34.0.txt +++ b/Documentation/RelNotes/2.34.0.adoc diff --git a/Documentation/RelNotes/2.34.1.txt b/Documentation/RelNotes/2.34.1.adoc index ad404e9aa0..ad404e9aa0 100644 --- a/Documentation/RelNotes/2.34.1.txt +++ b/Documentation/RelNotes/2.34.1.adoc diff --git a/Documentation/RelNotes/2.34.2.txt b/Documentation/RelNotes/2.34.2.adoc index 0c32cd844b..0c32cd844b 100644 --- a/Documentation/RelNotes/2.34.2.txt +++ b/Documentation/RelNotes/2.34.2.adoc diff --git a/Documentation/RelNotes/2.34.3.txt b/Documentation/RelNotes/2.34.3.adoc index 10f6171ace..10f6171ace 100644 --- a/Documentation/RelNotes/2.34.3.txt +++ b/Documentation/RelNotes/2.34.3.adoc diff --git a/Documentation/RelNotes/2.34.4.txt b/Documentation/RelNotes/2.34.4.adoc index 2a6b223403..2a6b223403 100644 --- a/Documentation/RelNotes/2.34.4.txt +++ b/Documentation/RelNotes/2.34.4.adoc diff --git a/Documentation/RelNotes/2.34.5.txt b/Documentation/RelNotes/2.34.5.adoc index 0e8999204d..0e8999204d 100644 --- a/Documentation/RelNotes/2.34.5.txt +++ b/Documentation/RelNotes/2.34.5.adoc diff --git a/Documentation/RelNotes/2.34.6.txt b/Documentation/RelNotes/2.34.6.adoc index b32080dba8..b32080dba8 100644 --- a/Documentation/RelNotes/2.34.6.txt +++ b/Documentation/RelNotes/2.34.6.adoc diff --git a/Documentation/RelNotes/2.34.7.txt b/Documentation/RelNotes/2.34.7.adoc index 88898adacc..88898adacc 100644 --- a/Documentation/RelNotes/2.34.7.txt +++ b/Documentation/RelNotes/2.34.7.adoc diff --git a/Documentation/RelNotes/2.34.8.txt b/Documentation/RelNotes/2.34.8.adoc index 2b5bd7d9a3..2b5bd7d9a3 100644 --- a/Documentation/RelNotes/2.34.8.txt +++ b/Documentation/RelNotes/2.34.8.adoc diff --git a/Documentation/RelNotes/2.35.0.txt b/Documentation/RelNotes/2.35.0.adoc index d69b50d180..d69b50d180 100644 --- a/Documentation/RelNotes/2.35.0.txt +++ b/Documentation/RelNotes/2.35.0.adoc diff --git a/Documentation/RelNotes/2.35.1.txt b/Documentation/RelNotes/2.35.1.adoc index 726ba250ef..726ba250ef 100644 --- a/Documentation/RelNotes/2.35.1.txt +++ b/Documentation/RelNotes/2.35.1.adoc diff --git a/Documentation/RelNotes/2.35.2.txt b/Documentation/RelNotes/2.35.2.adoc index 290bfa9ea4..290bfa9ea4 100644 --- a/Documentation/RelNotes/2.35.2.txt +++ b/Documentation/RelNotes/2.35.2.adoc diff --git a/Documentation/RelNotes/2.35.3.txt b/Documentation/RelNotes/2.35.3.adoc index 5458ba3441..5458ba3441 100644 --- a/Documentation/RelNotes/2.35.3.txt +++ b/Documentation/RelNotes/2.35.3.adoc diff --git a/Documentation/RelNotes/2.35.4.txt b/Documentation/RelNotes/2.35.4.adoc index 47abd5ad45..47abd5ad45 100644 --- a/Documentation/RelNotes/2.35.4.txt +++ b/Documentation/RelNotes/2.35.4.adoc diff --git a/Documentation/RelNotes/2.35.5.txt b/Documentation/RelNotes/2.35.5.adoc index e19cc48b33..e19cc48b33 100644 --- a/Documentation/RelNotes/2.35.5.txt +++ b/Documentation/RelNotes/2.35.5.adoc diff --git a/Documentation/RelNotes/2.35.6.txt b/Documentation/RelNotes/2.35.6.adoc index e7ca57bb41..e7ca57bb41 100644 --- a/Documentation/RelNotes/2.35.6.txt +++ b/Documentation/RelNotes/2.35.6.adoc diff --git a/Documentation/RelNotes/2.35.7.txt b/Documentation/RelNotes/2.35.7.adoc index 42baabfc3b..42baabfc3b 100644 --- a/Documentation/RelNotes/2.35.7.txt +++ b/Documentation/RelNotes/2.35.7.adoc diff --git a/Documentation/RelNotes/2.35.8.txt b/Documentation/RelNotes/2.35.8.adoc index 3c9c094c2b..3c9c094c2b 100644 --- a/Documentation/RelNotes/2.35.8.txt +++ b/Documentation/RelNotes/2.35.8.adoc diff --git a/Documentation/RelNotes/2.36.0.txt b/Documentation/RelNotes/2.36.0.adoc index e477fba12d..e477fba12d 100644 --- a/Documentation/RelNotes/2.36.0.txt +++ b/Documentation/RelNotes/2.36.0.adoc diff --git a/Documentation/RelNotes/2.36.1.txt b/Documentation/RelNotes/2.36.1.adoc index a9617095db..a9617095db 100644 --- a/Documentation/RelNotes/2.36.1.txt +++ b/Documentation/RelNotes/2.36.1.adoc diff --git a/Documentation/RelNotes/2.36.2.txt b/Documentation/RelNotes/2.36.2.adoc index 958f5b4102..958f5b4102 100644 --- a/Documentation/RelNotes/2.36.2.txt +++ b/Documentation/RelNotes/2.36.2.adoc diff --git a/Documentation/RelNotes/2.36.3.txt b/Documentation/RelNotes/2.36.3.adoc index 56db77b5bd..56db77b5bd 100644 --- a/Documentation/RelNotes/2.36.3.txt +++ b/Documentation/RelNotes/2.36.3.adoc diff --git a/Documentation/RelNotes/2.36.4.txt b/Documentation/RelNotes/2.36.4.adoc index 58fb93a35f..58fb93a35f 100644 --- a/Documentation/RelNotes/2.36.4.txt +++ b/Documentation/RelNotes/2.36.4.adoc diff --git a/Documentation/RelNotes/2.36.5.txt b/Documentation/RelNotes/2.36.5.adoc index 8a098c7916..8a098c7916 100644 --- a/Documentation/RelNotes/2.36.5.txt +++ b/Documentation/RelNotes/2.36.5.adoc diff --git a/Documentation/RelNotes/2.36.6.txt b/Documentation/RelNotes/2.36.6.adoc index e1edebcc43..e1edebcc43 100644 --- a/Documentation/RelNotes/2.36.6.txt +++ b/Documentation/RelNotes/2.36.6.adoc diff --git a/Documentation/RelNotes/2.37.0.txt b/Documentation/RelNotes/2.37.0.adoc index 99dc7e32f8..99dc7e32f8 100644 --- a/Documentation/RelNotes/2.37.0.txt +++ b/Documentation/RelNotes/2.37.0.adoc diff --git a/Documentation/RelNotes/2.37.1.txt b/Documentation/RelNotes/2.37.1.adoc index 84609327d1..84609327d1 100644 --- a/Documentation/RelNotes/2.37.1.txt +++ b/Documentation/RelNotes/2.37.1.adoc diff --git a/Documentation/RelNotes/2.37.2.txt b/Documentation/RelNotes/2.37.2.adoc index d82b29e014..d82b29e014 100644 --- a/Documentation/RelNotes/2.37.2.txt +++ b/Documentation/RelNotes/2.37.2.adoc diff --git a/Documentation/RelNotes/2.37.3.txt b/Documentation/RelNotes/2.37.3.adoc index d66689e598..d66689e598 100644 --- a/Documentation/RelNotes/2.37.3.txt +++ b/Documentation/RelNotes/2.37.3.adoc diff --git a/Documentation/RelNotes/2.37.4.txt b/Documentation/RelNotes/2.37.4.adoc index e42a5c1620..e42a5c1620 100644 --- a/Documentation/RelNotes/2.37.4.txt +++ b/Documentation/RelNotes/2.37.4.adoc diff --git a/Documentation/RelNotes/2.37.5.txt b/Documentation/RelNotes/2.37.5.adoc index faa1447292..faa1447292 100644 --- a/Documentation/RelNotes/2.37.5.txt +++ b/Documentation/RelNotes/2.37.5.adoc diff --git a/Documentation/RelNotes/2.37.6.txt b/Documentation/RelNotes/2.37.6.adoc index 51dc149711..51dc149711 100644 --- a/Documentation/RelNotes/2.37.6.txt +++ b/Documentation/RelNotes/2.37.6.adoc diff --git a/Documentation/RelNotes/2.37.7.txt b/Documentation/RelNotes/2.37.7.adoc index 4b8165f4b5..4b8165f4b5 100644 --- a/Documentation/RelNotes/2.37.7.txt +++ b/Documentation/RelNotes/2.37.7.adoc diff --git a/Documentation/RelNotes/2.38.0.txt b/Documentation/RelNotes/2.38.0.adoc index 870581fc57..870581fc57 100644 --- a/Documentation/RelNotes/2.38.0.txt +++ b/Documentation/RelNotes/2.38.0.adoc diff --git a/Documentation/RelNotes/2.38.1.txt b/Documentation/RelNotes/2.38.1.adoc index b2b5854aac..b2b5854aac 100644 --- a/Documentation/RelNotes/2.38.1.txt +++ b/Documentation/RelNotes/2.38.1.adoc diff --git a/Documentation/RelNotes/2.38.2.txt b/Documentation/RelNotes/2.38.2.adoc index 92acb62bbb..92acb62bbb 100644 --- a/Documentation/RelNotes/2.38.2.txt +++ b/Documentation/RelNotes/2.38.2.adoc diff --git a/Documentation/RelNotes/2.38.3.txt b/Documentation/RelNotes/2.38.3.adoc index 4a46bb4300..4a46bb4300 100644 --- a/Documentation/RelNotes/2.38.3.txt +++ b/Documentation/RelNotes/2.38.3.adoc diff --git a/Documentation/RelNotes/2.38.4.txt b/Documentation/RelNotes/2.38.4.adoc index fdfde22022..fdfde22022 100644 --- a/Documentation/RelNotes/2.38.4.txt +++ b/Documentation/RelNotes/2.38.4.adoc diff --git a/Documentation/RelNotes/2.38.5.txt b/Documentation/RelNotes/2.38.5.adoc index 2d1f3b1249..2d1f3b1249 100644 --- a/Documentation/RelNotes/2.38.5.txt +++ b/Documentation/RelNotes/2.38.5.adoc diff --git a/Documentation/RelNotes/2.39.0.txt b/Documentation/RelNotes/2.39.0.adoc index 9bf00ece53..9bf00ece53 100644 --- a/Documentation/RelNotes/2.39.0.txt +++ b/Documentation/RelNotes/2.39.0.adoc diff --git a/Documentation/RelNotes/2.39.1.txt b/Documentation/RelNotes/2.39.1.adoc index 60c86f4122..60c86f4122 100644 --- a/Documentation/RelNotes/2.39.1.txt +++ b/Documentation/RelNotes/2.39.1.adoc diff --git a/Documentation/RelNotes/2.39.2.txt b/Documentation/RelNotes/2.39.2.adoc index ebb9900bc5..ebb9900bc5 100644 --- a/Documentation/RelNotes/2.39.2.txt +++ b/Documentation/RelNotes/2.39.2.adoc diff --git a/Documentation/RelNotes/2.39.3.txt b/Documentation/RelNotes/2.39.3.adoc index 66351b65c2..66351b65c2 100644 --- a/Documentation/RelNotes/2.39.3.txt +++ b/Documentation/RelNotes/2.39.3.adoc diff --git a/Documentation/RelNotes/2.39.4.txt b/Documentation/RelNotes/2.39.4.adoc index 7f54521fea..7f54521fea 100644 --- a/Documentation/RelNotes/2.39.4.txt +++ b/Documentation/RelNotes/2.39.4.adoc diff --git a/Documentation/RelNotes/2.39.5.txt b/Documentation/RelNotes/2.39.5.adoc index 97c0185de4..97c0185de4 100644 --- a/Documentation/RelNotes/2.39.5.txt +++ b/Documentation/RelNotes/2.39.5.adoc diff --git a/Documentation/RelNotes/2.4.0.txt b/Documentation/RelNotes/2.4.0.adoc index cde64be535..cde64be535 100644 --- a/Documentation/RelNotes/2.4.0.txt +++ b/Documentation/RelNotes/2.4.0.adoc diff --git a/Documentation/RelNotes/2.4.1.txt b/Documentation/RelNotes/2.4.1.adoc index a65a6c5829..a65a6c5829 100644 --- a/Documentation/RelNotes/2.4.1.txt +++ b/Documentation/RelNotes/2.4.1.adoc diff --git a/Documentation/RelNotes/2.4.10.txt b/Documentation/RelNotes/2.4.10.adoc index 702d8d4e22..702d8d4e22 100644 --- a/Documentation/RelNotes/2.4.10.txt +++ b/Documentation/RelNotes/2.4.10.adoc diff --git a/Documentation/RelNotes/2.4.11.txt b/Documentation/RelNotes/2.4.11.adoc index 723360295c..723360295c 100644 --- a/Documentation/RelNotes/2.4.11.txt +++ b/Documentation/RelNotes/2.4.11.adoc diff --git a/Documentation/RelNotes/2.4.12.txt b/Documentation/RelNotes/2.4.12.adoc index 7d15f94725..7d15f94725 100644 --- a/Documentation/RelNotes/2.4.12.txt +++ b/Documentation/RelNotes/2.4.12.adoc diff --git a/Documentation/RelNotes/2.4.2.txt b/Documentation/RelNotes/2.4.2.adoc index 250cdc423c..250cdc423c 100644 --- a/Documentation/RelNotes/2.4.2.txt +++ b/Documentation/RelNotes/2.4.2.adoc diff --git a/Documentation/RelNotes/2.4.3.txt b/Documentation/RelNotes/2.4.3.adoc index 422e930aa2..422e930aa2 100644 --- a/Documentation/RelNotes/2.4.3.txt +++ b/Documentation/RelNotes/2.4.3.adoc diff --git a/Documentation/RelNotes/2.4.4.txt b/Documentation/RelNotes/2.4.4.adoc index f1ccd001be..f1ccd001be 100644 --- a/Documentation/RelNotes/2.4.4.txt +++ b/Documentation/RelNotes/2.4.4.adoc diff --git a/Documentation/RelNotes/2.4.5.txt b/Documentation/RelNotes/2.4.5.adoc index 568297ccb7..568297ccb7 100644 --- a/Documentation/RelNotes/2.4.5.txt +++ b/Documentation/RelNotes/2.4.5.adoc diff --git a/Documentation/RelNotes/2.4.6.txt b/Documentation/RelNotes/2.4.6.adoc index b53f353939..b53f353939 100644 --- a/Documentation/RelNotes/2.4.6.txt +++ b/Documentation/RelNotes/2.4.6.adoc diff --git a/Documentation/RelNotes/2.4.7.txt b/Documentation/RelNotes/2.4.7.adoc index b3ac412b82..b3ac412b82 100644 --- a/Documentation/RelNotes/2.4.7.txt +++ b/Documentation/RelNotes/2.4.7.adoc diff --git a/Documentation/RelNotes/2.4.8.txt b/Documentation/RelNotes/2.4.8.adoc index ad946b2673..ad946b2673 100644 --- a/Documentation/RelNotes/2.4.8.txt +++ b/Documentation/RelNotes/2.4.8.adoc diff --git a/Documentation/RelNotes/2.4.9.txt b/Documentation/RelNotes/2.4.9.adoc index 09af9ddbc7..09af9ddbc7 100644 --- a/Documentation/RelNotes/2.4.9.txt +++ b/Documentation/RelNotes/2.4.9.adoc diff --git a/Documentation/RelNotes/2.40.0.txt b/Documentation/RelNotes/2.40.0.adoc index 3ea445bf20..3ea445bf20 100644 --- a/Documentation/RelNotes/2.40.0.txt +++ b/Documentation/RelNotes/2.40.0.adoc diff --git a/Documentation/RelNotes/2.40.1.txt b/Documentation/RelNotes/2.40.1.adoc index e72f6b1b25..e72f6b1b25 100644 --- a/Documentation/RelNotes/2.40.1.txt +++ b/Documentation/RelNotes/2.40.1.adoc diff --git a/Documentation/RelNotes/2.40.2.txt b/Documentation/RelNotes/2.40.2.adoc index 646a2cc3eb..646a2cc3eb 100644 --- a/Documentation/RelNotes/2.40.2.txt +++ b/Documentation/RelNotes/2.40.2.adoc diff --git a/Documentation/RelNotes/2.40.3.txt b/Documentation/RelNotes/2.40.3.adoc index 6ca088ec86..6ca088ec86 100644 --- a/Documentation/RelNotes/2.40.3.txt +++ b/Documentation/RelNotes/2.40.3.adoc diff --git a/Documentation/RelNotes/2.40.4.txt b/Documentation/RelNotes/2.40.4.adoc index 0ff29f3cfc..0ff29f3cfc 100644 --- a/Documentation/RelNotes/2.40.4.txt +++ b/Documentation/RelNotes/2.40.4.adoc diff --git a/Documentation/RelNotes/2.41.0.txt b/Documentation/RelNotes/2.41.0.adoc index 8a9e17016e..8a9e17016e 100644 --- a/Documentation/RelNotes/2.41.0.txt +++ b/Documentation/RelNotes/2.41.0.adoc diff --git a/Documentation/RelNotes/2.41.1.txt b/Documentation/RelNotes/2.41.1.adoc index 9fb4c218b2..9fb4c218b2 100644 --- a/Documentation/RelNotes/2.41.1.txt +++ b/Documentation/RelNotes/2.41.1.adoc diff --git a/Documentation/RelNotes/2.41.2.txt b/Documentation/RelNotes/2.41.2.adoc index f94afde8c2..f94afde8c2 100644 --- a/Documentation/RelNotes/2.41.2.txt +++ b/Documentation/RelNotes/2.41.2.adoc diff --git a/Documentation/RelNotes/2.41.3.txt b/Documentation/RelNotes/2.41.3.adoc index b5aba88790..b5aba88790 100644 --- a/Documentation/RelNotes/2.41.3.txt +++ b/Documentation/RelNotes/2.41.3.adoc diff --git a/Documentation/RelNotes/2.42.0.txt b/Documentation/RelNotes/2.42.0.adoc index 0f1897ad5f..0f1897ad5f 100644 --- a/Documentation/RelNotes/2.42.0.txt +++ b/Documentation/RelNotes/2.42.0.adoc diff --git a/Documentation/RelNotes/2.42.1.txt b/Documentation/RelNotes/2.42.1.adoc index 3d391b7dcd..3d391b7dcd 100644 --- a/Documentation/RelNotes/2.42.1.txt +++ b/Documentation/RelNotes/2.42.1.adoc diff --git a/Documentation/RelNotes/2.42.2.txt b/Documentation/RelNotes/2.42.2.adoc index dbf761a01d..dbf761a01d 100644 --- a/Documentation/RelNotes/2.42.2.txt +++ b/Documentation/RelNotes/2.42.2.adoc diff --git a/Documentation/RelNotes/2.42.3.txt b/Documentation/RelNotes/2.42.3.adoc index bfe3ba5629..bfe3ba5629 100644 --- a/Documentation/RelNotes/2.42.3.txt +++ b/Documentation/RelNotes/2.42.3.adoc diff --git a/Documentation/RelNotes/2.42.4.txt b/Documentation/RelNotes/2.42.4.adoc index 3129d76e75..3129d76e75 100644 --- a/Documentation/RelNotes/2.42.4.txt +++ b/Documentation/RelNotes/2.42.4.adoc diff --git a/Documentation/RelNotes/2.43.0.txt b/Documentation/RelNotes/2.43.0.adoc index e0e5b535bb..e0e5b535bb 100644 --- a/Documentation/RelNotes/2.43.0.txt +++ b/Documentation/RelNotes/2.43.0.adoc diff --git a/Documentation/RelNotes/2.43.1.txt b/Documentation/RelNotes/2.43.1.adoc index 20e96f2dfa..20e96f2dfa 100644 --- a/Documentation/RelNotes/2.43.1.txt +++ b/Documentation/RelNotes/2.43.1.adoc diff --git a/Documentation/RelNotes/2.43.2.txt b/Documentation/RelNotes/2.43.2.adoc index 5895e23a54..5895e23a54 100644 --- a/Documentation/RelNotes/2.43.2.txt +++ b/Documentation/RelNotes/2.43.2.adoc diff --git a/Documentation/RelNotes/2.43.3.txt b/Documentation/RelNotes/2.43.3.adoc index 924f20594f..924f20594f 100644 --- a/Documentation/RelNotes/2.43.3.txt +++ b/Documentation/RelNotes/2.43.3.adoc diff --git a/Documentation/RelNotes/2.43.4.txt b/Documentation/RelNotes/2.43.4.adoc index 0a842515ff..0a842515ff 100644 --- a/Documentation/RelNotes/2.43.4.txt +++ b/Documentation/RelNotes/2.43.4.adoc diff --git a/Documentation/RelNotes/2.43.5.txt b/Documentation/RelNotes/2.43.5.adoc index 236b234b06..236b234b06 100644 --- a/Documentation/RelNotes/2.43.5.txt +++ b/Documentation/RelNotes/2.43.5.adoc diff --git a/Documentation/RelNotes/2.43.6.txt b/Documentation/RelNotes/2.43.6.adoc index 2114b9f78d..2114b9f78d 100644 --- a/Documentation/RelNotes/2.43.6.txt +++ b/Documentation/RelNotes/2.43.6.adoc diff --git a/Documentation/RelNotes/2.44.0.txt b/Documentation/RelNotes/2.44.0.adoc index 14f9ce8226..14f9ce8226 100644 --- a/Documentation/RelNotes/2.44.0.txt +++ b/Documentation/RelNotes/2.44.0.adoc diff --git a/Documentation/RelNotes/2.44.1.txt b/Documentation/RelNotes/2.44.1.adoc index b5135c3281..b5135c3281 100644 --- a/Documentation/RelNotes/2.44.1.txt +++ b/Documentation/RelNotes/2.44.1.adoc diff --git a/Documentation/RelNotes/2.44.2.txt b/Documentation/RelNotes/2.44.2.adoc index 76700f0b73..76700f0b73 100644 --- a/Documentation/RelNotes/2.44.2.txt +++ b/Documentation/RelNotes/2.44.2.adoc diff --git a/Documentation/RelNotes/2.44.3.txt b/Documentation/RelNotes/2.44.3.adoc index 5862845458..5862845458 100644 --- a/Documentation/RelNotes/2.44.3.txt +++ b/Documentation/RelNotes/2.44.3.adoc diff --git a/Documentation/RelNotes/2.45.0.txt b/Documentation/RelNotes/2.45.0.adoc index aa0315259b..aa0315259b 100644 --- a/Documentation/RelNotes/2.45.0.txt +++ b/Documentation/RelNotes/2.45.0.adoc diff --git a/Documentation/RelNotes/2.45.1.txt b/Documentation/RelNotes/2.45.1.adoc index 3b0d60cfa3..3b0d60cfa3 100644 --- a/Documentation/RelNotes/2.45.1.txt +++ b/Documentation/RelNotes/2.45.1.adoc diff --git a/Documentation/RelNotes/2.45.2.txt b/Documentation/RelNotes/2.45.2.adoc index 13429e6491..13429e6491 100644 --- a/Documentation/RelNotes/2.45.2.txt +++ b/Documentation/RelNotes/2.45.2.adoc diff --git a/Documentation/RelNotes/2.45.3.txt b/Documentation/RelNotes/2.45.3.adoc index ddb3cb694b..ddb3cb694b 100644 --- a/Documentation/RelNotes/2.45.3.txt +++ b/Documentation/RelNotes/2.45.3.adoc diff --git a/Documentation/RelNotes/2.46.0.txt b/Documentation/RelNotes/2.46.0.adoc index c06a04a91b..c06a04a91b 100644 --- a/Documentation/RelNotes/2.46.0.txt +++ b/Documentation/RelNotes/2.46.0.adoc diff --git a/Documentation/RelNotes/2.46.1.txt b/Documentation/RelNotes/2.46.1.adoc index e55c2c4a46..e55c2c4a46 100644 --- a/Documentation/RelNotes/2.46.1.txt +++ b/Documentation/RelNotes/2.46.1.adoc diff --git a/Documentation/RelNotes/2.46.2.txt b/Documentation/RelNotes/2.46.2.adoc index 613386878d..613386878d 100644 --- a/Documentation/RelNotes/2.46.2.txt +++ b/Documentation/RelNotes/2.46.2.adoc diff --git a/Documentation/RelNotes/2.46.3.txt b/Documentation/RelNotes/2.46.3.adoc index 4af032b63c..4af032b63c 100644 --- a/Documentation/RelNotes/2.46.3.txt +++ b/Documentation/RelNotes/2.46.3.adoc diff --git a/Documentation/RelNotes/2.47.0.txt b/Documentation/RelNotes/2.47.0.adoc index b63c3364af..b63c3364af 100644 --- a/Documentation/RelNotes/2.47.0.txt +++ b/Documentation/RelNotes/2.47.0.adoc diff --git a/Documentation/RelNotes/2.47.1.txt b/Documentation/RelNotes/2.47.1.adoc index 39206c09fd..39206c09fd 100644 --- a/Documentation/RelNotes/2.47.1.txt +++ b/Documentation/RelNotes/2.47.1.adoc diff --git a/Documentation/RelNotes/2.47.2.txt b/Documentation/RelNotes/2.47.2.adoc index 7a52ad8cb4..7a52ad8cb4 100644 --- a/Documentation/RelNotes/2.47.2.txt +++ b/Documentation/RelNotes/2.47.2.adoc diff --git a/Documentation/RelNotes/2.48.0.txt b/Documentation/RelNotes/2.48.0.adoc index eff93be37a..eff93be37a 100644 --- a/Documentation/RelNotes/2.48.0.txt +++ b/Documentation/RelNotes/2.48.0.adoc diff --git a/Documentation/RelNotes/2.48.1.txt b/Documentation/RelNotes/2.48.1.adoc index 26c59b6e3b..26c59b6e3b 100644 --- a/Documentation/RelNotes/2.48.1.txt +++ b/Documentation/RelNotes/2.48.1.adoc diff --git a/Documentation/RelNotes/2.49.0.adoc b/Documentation/RelNotes/2.49.0.adoc new file mode 100644 index 0000000000..494c83096f --- /dev/null +++ b/Documentation/RelNotes/2.49.0.adoc @@ -0,0 +1,288 @@ +Git v2.49 Release Notes +======================= + +UI, Workflows & Features +------------------------ + + * Completion script updates for zsh + + * "git pack-objects" and its wrapper "git repack" learned an option + to use an alternative path-hash function to improve delta-base + selection to produce a packfile with deeper history than window + size. + + * "git gc" learned the "--expire-to" option and passes it down to + underlying "git repack". + + * "[help] autocorrect = 1" used to be a way to say "please wait for + 0.1 second after suggesting a typofix of the command name before + running that command"; now it means "yes, if there is a plausible + typofix for the command name, please run it immediately". + + * "git clone" learned to make a shallow clone for a single commit + that is not necessarily be at the tip of any branch. + + * Lazy-loading missing files in a blobless clone on demand is costly + as it tends to be one-blob-at-a-time. "git backfill" is introduced + to help bulk-download necessary files beforehand. + + * "git push --atomic --porcelain" used to ignore failures from the + other side, losing the error status from the child process, which + has been corrected. + + * "git rev-list --missing=" learned to accept "print-info" that gives + known details expected of the missing objects, like path and type. + + * Comes with an updated "gitk". + + * The documentation of "git commit" and "git rebase" now refer to + commit titles as such, not "subject". + + * The value of "uname -s" is by default sent over the wire as a part + of the "version" capability. + + * "git refs migrate" can optionally be told not to migrate the reflog. + + * The netrc support (via the cURL library) for the HTTP transport has + been re-enabled. + + * Removal of ".git/branches" and ".git/remotes" support in the + BreakingChanges document has been further clarified. + + * What happens to submodules during merge has been documented in a + bit more detail. + + +Performance, Internal Implementation, Development Support etc. +-------------------------------------------------------------- + + * More -Wsign-compare fixes. + + * meson-based build now supports the unsafe-sha1 build knob. + + * The meson-based build procedure covers contrib/ and other places as + well. + + * The code to check LSan results has been simplified and made more + robust. + (merge 164a2516eb jk/lsan-race-ignore-false-positive later to maint). + + * More code paths have a repository passed through the callchain, + instead of assuming the primary the_repository object. + + * Move a few more unit tests to the clar test framework. + + * Introduce a new API to visit objects in batches based on a common + path, or by type. + + * Following the procedure we established to introduce breaking + changes for Git 3.0, allow an early opt-in for removing support of + $GIT_DIR/branches/ and $GIT_DIR/remotes/ directories to configure + remotes. + + * The code paths to interact with zlib has been cleaned up in + preparation for building with zlib-ng. + + * Foreign language interface for Rust into our code base has been added. + + * All the documentation .txt files have been renamed to .adoc to help + content aware editors. + + * "git difftool" code clean-up. + + * Rename processing in the recursive merge backend has seen a micro + optimization. + + * The path.[ch] API takes an explicit repository parameter passed + throughout the callchain, instead of relying on the_repository + singleton instance. + + * Large-object promisor protocol extension has been introduced. + + * The editorconfig file is updated to tell us that bash scripts are + similar to general Bourne shell scripts. + + * Meson-based build procedure forgot to build some docs, which has + been corrected. + + +Fixes since v2.48 +----------------- + + * "git submodule" learned various ways to spell the same option, + e.g. "--branch=B" can be spelled "--branch B" or "-bB". + (merge b86f0f9071 re/submodule-parse-opt later to maint). + + * Tweak the help text used for the option value placeholders by + parse-options API so that translations can customize the "<>" + placeholder signal (e.g. "--option=<value>"). + (merge 5b34dd08d0 as/long-option-help-i18n later to maint). + + * CI jobs gave sporadic failures, which turns out that that the + object finalization code was giving an error when it did not have + to. + (merge d7fcbe2c56 ps/object-collision-check later to maint). + + * The code to compute "unique" name used git_rand() which can fail or + get stuck; the callsite does not require cryptographic security. + Introduce the "insecure" mode and use it appropriately. + (merge 0b4f8afef6 ps/reftable-get-random-fix later to maint). + + * A misconfigured "fsck.skiplist" configuration variable was not + diagnosed as an error, which has been corrected. + (merge ca7158076f jt/fsck-skiplist-parse-fix later to maint). + + * Extended SHA-1 expression parser did not work well when a branch + with an unusual name (e.g. "foo{bar") is involved. + (merge 191f0c8db2 en/object-name-with-funny-refname-fix later to maint). + + * The meson build procedure looked for the 'version-def.h' file in a + wrong directory, which has been corrected. + (merge 4771501c0a tc/meson-use-our-version-def-h later to maint). + + * The meson build procedure for Documentation/technical/ hierarchy was + missing necessary dependencies, which has been corrected. + (merge 1dca492edd sj/meson-doc-technical-dependency-fix later to maint). + + * The "instaweb" bound only to local IP address without "--local" and + to all addresses with "--local", which was the other way around, when + using Python's http.server class, which has been corrected. + (merge 76baf97fa1 ak/instaweb-python-port-binding-fix later to maint). + + * Document that it is insecure to use Personal Access Tokens, which + some hosting providers take as username/password, embedded in URLs. + (merge a90ff409f0 mh/doc-credential-helpers-with-pat later to maint). + + * The help text from "git $cmd -h" appear on the standard output for + some $cmd and the standard error for others. The built-in commands + have been fixed to show them on the standard output consistently. + (merge f66d1423f5 jc/show-usage-help later to maint). + + * The meson-driven build is now aware of "git-subtree" housed in + contrib/subtree hierarchy. + (merge 8454b42f94 ps/build-meson-subtree later to maint). + + * It was possible for "git unpack-objects" and "git index-pack" to + make an unaligned access, which has been corrected. + (merge 98046591b9 jk/pack-header-parse-alignment-fix later to maint). + + * The "cache" credential back-end did not handle authtype correctly, + which has been corrected. + (merge 0b43274850 mh/credential-cache-authtype-request-fix later to maint). + + * "git branch --sort=..." and "git for-each-ref --format=... --sort=..." + did not work as expected with some atoms, which has been corrected. + (merge c5490ce9d1 rs/ref-fitler-used-atoms-value-fix later to maint). + + * reflog entries for symbolic ref updates were broken, which has been + corrected. + (merge 3519492430 kn/reflog-symref-fix later to maint). + + * The trace2 code was not prepared to show a configuration variable + that is set to true using the valueless true syntax, which has been + corrected. + (merge 2fd367cf63 am/trace2-with-valueless-true later to maint). + + * The "git refs migrate" command did not migrate the reflog for + refs/stash, which is the contents of the stashes, which has been + corrected. + (merge a0bea0978f ps/reflog-migration-with-logall-fix later to maint). + + * Doc and short-help text for "show-index" has been clarified to + stress that the command reads its data from the standard input. + (merge 49edce4ff9 jc/show-index-h-update later to maint). + + * The API around choosing to use unsafe variant of SHA-1 + implementation has been updated in an attempt to make it harder to + abuse. + (merge 04292c3796 tb/unsafe-hash-cleanup later to maint). + + * Fix bugs in an earlier attempt to fix "git refs migration". + (merge f11f0a5a2d kn/reflog-migration-fix-fix later to maint). + + * The code path used when "git fetch" fetches from a bundle file + closed the same file descriptor twice, which sometimes broke things + unexpectedly when the file descriptor was reused, which has been + corrected. + (merge 9a84794ad8 js/bundle-unbundle-fd-reuse-fix later to maint). + + * "git init" to reinitialize a repository that already exists cannot + change the hash function and ref backends; such a request is + silently ignored now. + (merge 7e88640cd1 ps/setup-reinit-fixes later to maint). + + * "git apply" internally uses unsigned long for line numbers and uses + strtoul() to parse numbers on the hunk headers. It however forgot + to check parse errors. + (merge a206058fda pw/apply-ulong-overflow-check later to maint). + + * Two CI tasks, whitespace check and style check, work on the + difference from the base version and the version being checked, but + the base was computed incorrectly in GitLab CI in some cases, which + has been corrected. + (merge acc4fb302b jt/gitlab-ci-base-fix later to maint). + + * "git repack --keep-unreachable" to send unreachable objects to the + main pack "git repack -ad" produces did not work when there is no + existing packs, which has been corrected. + (merge 414c82300a ps/repack-keep-unreachable-in-unpacked-repo later to maint). + + * Going into a secondary worktree and asking "is the main worktree + bare?" did not work correctly when per-worktree configuration + option was in use, which has been corrected. + + * Fetching into a bare repository incorrectly assumed it always used + a mirror layout when deciding to update remote-tracking HEAD, which + has been corrected. + (merge 93dc16483a bf/fetch-set-head-fix later to maint). + + * A thunderbird helper script lost its bashism. + (merge 59d26bd961 bc/contrib-thunderbird-patch-inline-fix later to maint). + + * The -G/-S options to the "diff" family of commands caused us to hit + a BUG() when they get no values; they have been corrected. + (merge a620046b29 bc/diff-reject-empty-arg-to-pickaxe later to maint). + + * "git merge-tree --stdin" has been improved (including a workaround + for a deadlock). + (merge 6a9ae81015 pw/merge-tree-stdin-deadlock-fix later to maint). + + * Correct the default target in Documentation/Makefile, and + future-proof all Makefiles from similar breakages by declaring the + default target (which happens to be "all") upfront. + (merge 5309c1e9fb ad/set-default-target-in-makefiles later to maint). + + * "git check-mailmap" used to segfault when queried without human + readable name. + (merge bb60c52131 jk/check-mailmap-wo-name-fix later to maint). + + * Support for renaming of symbolic links on Windows has been improved. + + * "git rebase -i" failed to allow rewording an empty commit that has + been fast-forwarded. + (merge af8fc7be10 pw/rebase-i-ff-empty-commit later to maint). + + * The use of "paste" command for aggregating the test results have + been corrected. + (merge ce98863204 dk/test-aggregate-results-paste-fix later to maint). + + * Other code cleanup, docfix, build fix, etc. + (merge ddb5287894 jk/t7407-use-test-grep later to maint). + (merge 21e1b44865 aj/difftool-config-doc-fix later to maint). + (merge 6a63995335 mh/gitattr-doc-markup-fix later to maint). + (merge 43850dcf9c sk/unit-test-hash later to maint). + (merge 4ad47d2de3 jc/cli-doc-option-and-config later to maint). + (merge 2d0ff147e5 jp/t8002-printf-fix later to maint). + (merge 69666e6746 ja/doc-restore-markup-update later to maint). + (merge d11d003ba5 sk/strlen-returns-size_t later to maint). + (merge 77b2d29e91 ja/doc-notes-markup-updates later to maint). + (merge 6979bf6f8f jk/combine-diff-cleanup later to maint). + (merge 8705c9bd13 kn/pack-write-with-reduced-globals later to maint). + (merge 087740d65a ps/leakfixes-0129 later to maint). + (merge 6bba6f604b jp/doc-trailer-config later to maint). + (merge f1cc562b77 lo/t7603-path-is-file-update later to maint). + (merge 45761988ac en/doc-renormalize later to maint). + (merge 832f56f06a jc/doc-boolean-synonyms later to maint). + (merge 3eeed876a9 ac/doc-http-ssl-type-config later to maint). + (merge c268e3285d jc/breaking-changes-early-adopter-option later to maint). + (merge 0d03fda6a5 pb/doc-follow-remote-head later to maint). diff --git a/Documentation/RelNotes/2.5.0.txt b/Documentation/RelNotes/2.5.0.adoc index 84723f912a..84723f912a 100644 --- a/Documentation/RelNotes/2.5.0.txt +++ b/Documentation/RelNotes/2.5.0.adoc diff --git a/Documentation/RelNotes/2.5.1.txt b/Documentation/RelNotes/2.5.1.adoc index b70553308a..b70553308a 100644 --- a/Documentation/RelNotes/2.5.1.txt +++ b/Documentation/RelNotes/2.5.1.adoc diff --git a/Documentation/RelNotes/2.5.2.txt b/Documentation/RelNotes/2.5.2.adoc index 3f749398bb..3f749398bb 100644 --- a/Documentation/RelNotes/2.5.2.txt +++ b/Documentation/RelNotes/2.5.2.adoc diff --git a/Documentation/RelNotes/2.5.3.txt b/Documentation/RelNotes/2.5.3.adoc index d1436857cb..d1436857cb 100644 --- a/Documentation/RelNotes/2.5.3.txt +++ b/Documentation/RelNotes/2.5.3.adoc diff --git a/Documentation/RelNotes/2.5.4.txt b/Documentation/RelNotes/2.5.4.adoc index b8a2f93ee7..b8a2f93ee7 100644 --- a/Documentation/RelNotes/2.5.4.txt +++ b/Documentation/RelNotes/2.5.4.adoc diff --git a/Documentation/RelNotes/2.5.5.txt b/Documentation/RelNotes/2.5.5.adoc index 37eae9a2d9..37eae9a2d9 100644 --- a/Documentation/RelNotes/2.5.5.txt +++ b/Documentation/RelNotes/2.5.5.adoc diff --git a/Documentation/RelNotes/2.5.6.txt b/Documentation/RelNotes/2.5.6.adoc index 9cd025bb1c..9cd025bb1c 100644 --- a/Documentation/RelNotes/2.5.6.txt +++ b/Documentation/RelNotes/2.5.6.adoc diff --git a/Documentation/RelNotes/2.50.0.adoc b/Documentation/RelNotes/2.50.0.adoc new file mode 100644 index 0000000000..50e3027984 --- /dev/null +++ b/Documentation/RelNotes/2.50.0.adoc @@ -0,0 +1,34 @@ +Git v2.50 Release Notes +======================= + +UI, Workflows & Features +------------------------ + + * A post-processing filter for "diff --raw" output has been + introduced. + + +Performance, Internal Implementation, Development Support etc. +-------------------------------------------------------------- + + * A handful of built-in command implementations have been rewritten + to use the repository instance supplied by git.c:run_builtin(), its + caller. + + * "git fsck" becomes more careful when checking the refs. + + +Fixes since v2.49 +----------------- + + * The refname exclusion logic in the packed-ref backend has been + broken for some time, which confused upload-pack to advertise + different set of refs. This has been corrected. + (merge 10e8a9352b tb/refs-exclude-fixes later to maint). + + * The merge-recursive and merge-ort machinery crashed in corner cases + when certain renames are involved. + (merge 3adba40858 en/merge-process-renames-crash-fix later to maint). + + * Other code cleanup, docfix, build fix, etc. + (merge 227c4f33a0 ja/doc-block-delimiter-markup-fix later to maint). diff --git a/Documentation/RelNotes/2.6.0.txt b/Documentation/RelNotes/2.6.0.adoc index 7288aaf716..7288aaf716 100644 --- a/Documentation/RelNotes/2.6.0.txt +++ b/Documentation/RelNotes/2.6.0.adoc diff --git a/Documentation/RelNotes/2.6.1.txt b/Documentation/RelNotes/2.6.1.adoc index f37ea89cda..f37ea89cda 100644 --- a/Documentation/RelNotes/2.6.1.txt +++ b/Documentation/RelNotes/2.6.1.adoc diff --git a/Documentation/RelNotes/2.6.2.txt b/Documentation/RelNotes/2.6.2.adoc index 5b65e35245..5b65e35245 100644 --- a/Documentation/RelNotes/2.6.2.txt +++ b/Documentation/RelNotes/2.6.2.adoc diff --git a/Documentation/RelNotes/2.6.3.txt b/Documentation/RelNotes/2.6.3.adoc index fc6fe1711f..fc6fe1711f 100644 --- a/Documentation/RelNotes/2.6.3.txt +++ b/Documentation/RelNotes/2.6.3.adoc diff --git a/Documentation/RelNotes/2.6.4.txt b/Documentation/RelNotes/2.6.4.adoc index b0256a2dc9..b0256a2dc9 100644 --- a/Documentation/RelNotes/2.6.4.txt +++ b/Documentation/RelNotes/2.6.4.adoc diff --git a/Documentation/RelNotes/2.6.5.txt b/Documentation/RelNotes/2.6.5.adoc index f0924b62e0..f0924b62e0 100644 --- a/Documentation/RelNotes/2.6.5.txt +++ b/Documentation/RelNotes/2.6.5.adoc diff --git a/Documentation/RelNotes/2.6.6.txt b/Documentation/RelNotes/2.6.6.adoc index 023ad85ec6..023ad85ec6 100644 --- a/Documentation/RelNotes/2.6.6.txt +++ b/Documentation/RelNotes/2.6.6.adoc diff --git a/Documentation/RelNotes/2.6.7.txt b/Documentation/RelNotes/2.6.7.adoc index 1335de49a6..1335de49a6 100644 --- a/Documentation/RelNotes/2.6.7.txt +++ b/Documentation/RelNotes/2.6.7.adoc diff --git a/Documentation/RelNotes/2.7.0.txt b/Documentation/RelNotes/2.7.0.adoc index e3cbf3a73c..e3cbf3a73c 100644 --- a/Documentation/RelNotes/2.7.0.txt +++ b/Documentation/RelNotes/2.7.0.adoc diff --git a/Documentation/RelNotes/2.7.1.txt b/Documentation/RelNotes/2.7.1.adoc index 6323feaf64..6323feaf64 100644 --- a/Documentation/RelNotes/2.7.1.txt +++ b/Documentation/RelNotes/2.7.1.adoc diff --git a/Documentation/RelNotes/2.7.2.txt b/Documentation/RelNotes/2.7.2.adoc index 4feef76704..4feef76704 100644 --- a/Documentation/RelNotes/2.7.2.txt +++ b/Documentation/RelNotes/2.7.2.adoc diff --git a/Documentation/RelNotes/2.7.3.txt b/Documentation/RelNotes/2.7.3.adoc index f618d71efd..f618d71efd 100644 --- a/Documentation/RelNotes/2.7.3.txt +++ b/Documentation/RelNotes/2.7.3.adoc diff --git a/Documentation/RelNotes/2.7.4.txt b/Documentation/RelNotes/2.7.4.adoc index 883ae896fe..883ae896fe 100644 --- a/Documentation/RelNotes/2.7.4.txt +++ b/Documentation/RelNotes/2.7.4.adoc diff --git a/Documentation/RelNotes/2.7.5.txt b/Documentation/RelNotes/2.7.5.adoc index 83559ce3b2..83559ce3b2 100644 --- a/Documentation/RelNotes/2.7.5.txt +++ b/Documentation/RelNotes/2.7.5.adoc diff --git a/Documentation/RelNotes/2.7.6.txt b/Documentation/RelNotes/2.7.6.adoc index 4c6d1dcd4a..4c6d1dcd4a 100644 --- a/Documentation/RelNotes/2.7.6.txt +++ b/Documentation/RelNotes/2.7.6.adoc diff --git a/Documentation/RelNotes/2.8.0.txt b/Documentation/RelNotes/2.8.0.adoc index 38453281b8..38453281b8 100644 --- a/Documentation/RelNotes/2.8.0.txt +++ b/Documentation/RelNotes/2.8.0.adoc diff --git a/Documentation/RelNotes/2.8.1.txt b/Documentation/RelNotes/2.8.1.adoc index ef6d80b008..ef6d80b008 100644 --- a/Documentation/RelNotes/2.8.1.txt +++ b/Documentation/RelNotes/2.8.1.adoc diff --git a/Documentation/RelNotes/2.8.2.txt b/Documentation/RelNotes/2.8.2.adoc index 447b1933a8..447b1933a8 100644 --- a/Documentation/RelNotes/2.8.2.txt +++ b/Documentation/RelNotes/2.8.2.adoc diff --git a/Documentation/RelNotes/2.8.3.txt b/Documentation/RelNotes/2.8.3.adoc index a63825ed87..a63825ed87 100644 --- a/Documentation/RelNotes/2.8.3.txt +++ b/Documentation/RelNotes/2.8.3.adoc diff --git a/Documentation/RelNotes/2.8.4.txt b/Documentation/RelNotes/2.8.4.adoc index f4e2552836..f4e2552836 100644 --- a/Documentation/RelNotes/2.8.4.txt +++ b/Documentation/RelNotes/2.8.4.adoc diff --git a/Documentation/RelNotes/2.8.5.txt b/Documentation/RelNotes/2.8.5.adoc index 7bd179fa12..7bd179fa12 100644 --- a/Documentation/RelNotes/2.8.5.txt +++ b/Documentation/RelNotes/2.8.5.adoc diff --git a/Documentation/RelNotes/2.8.6.txt b/Documentation/RelNotes/2.8.6.adoc index d8db55d920..d8db55d920 100644 --- a/Documentation/RelNotes/2.8.6.txt +++ b/Documentation/RelNotes/2.8.6.adoc diff --git a/Documentation/RelNotes/2.9.0.txt b/Documentation/RelNotes/2.9.0.adoc index 991640119a..991640119a 100644 --- a/Documentation/RelNotes/2.9.0.txt +++ b/Documentation/RelNotes/2.9.0.adoc diff --git a/Documentation/RelNotes/2.9.1.txt b/Documentation/RelNotes/2.9.1.adoc index 338394097e..338394097e 100644 --- a/Documentation/RelNotes/2.9.1.txt +++ b/Documentation/RelNotes/2.9.1.adoc diff --git a/Documentation/RelNotes/2.9.2.txt b/Documentation/RelNotes/2.9.2.adoc index 2620003dcf..2620003dcf 100644 --- a/Documentation/RelNotes/2.9.2.txt +++ b/Documentation/RelNotes/2.9.2.adoc diff --git a/Documentation/RelNotes/2.9.3.txt b/Documentation/RelNotes/2.9.3.adoc index 305e08062b..305e08062b 100644 --- a/Documentation/RelNotes/2.9.3.txt +++ b/Documentation/RelNotes/2.9.3.adoc diff --git a/Documentation/RelNotes/2.9.4.txt b/Documentation/RelNotes/2.9.4.adoc index 9768293831..9768293831 100644 --- a/Documentation/RelNotes/2.9.4.txt +++ b/Documentation/RelNotes/2.9.4.adoc diff --git a/Documentation/RelNotes/2.9.5.txt b/Documentation/RelNotes/2.9.5.adoc index 668313ae55..668313ae55 100644 --- a/Documentation/RelNotes/2.9.5.txt +++ b/Documentation/RelNotes/2.9.5.adoc diff --git a/Documentation/ReviewingGuidelines.txt b/Documentation/ReviewingGuidelines.adoc index 6534643cff..6534643cff 100644 --- a/Documentation/ReviewingGuidelines.txt +++ b/Documentation/ReviewingGuidelines.adoc diff --git a/Documentation/ToolsForGit.txt b/Documentation/ToolsForGit.adoc index ae7690b45d..a842c13327 100644 --- a/Documentation/ToolsForGit.txt +++ b/Documentation/ToolsForGit.adoc @@ -34,6 +34,7 @@ This is adapted from Linux's suggestion in its CodingStyle document: - To follow the rules in CodingGuidelines, it's useful to put the following in GIT_CHECKOUT/.dir-locals.el, assuming you use cperl-mode: + ---- ;; note the first part is useful for C editing, too ((nil . ((indent-tabs-mode . t) diff --git a/Documentation/blame-options.txt b/Documentation/blame-options.adoc index 552dcc60f2..aa77406d4e 100644 --- a/Documentation/blame-options.txt +++ b/Documentation/blame-options.adoc @@ -18,7 +18,7 @@ '<start>' and '<end>' are optional. `-L <start>` or `-L <start>,` spans from '<start>' to end of file. `-L ,<end>` spans from start of file to '<end>'. + -include::line-range-format.txt[] +include::line-range-format.adoc[] -l:: Show long rev (Default: off). diff --git a/Documentation/build-docdep.perl b/Documentation/build-docdep.perl index 315efaa2fa..781da12b2e 100755 --- a/Documentation/build-docdep.perl +++ b/Documentation/build-docdep.perl @@ -4,15 +4,15 @@ my ($build_dir) = @ARGV; my %include = (); my %included = (); -for my $text (<*.txt>) { - open I, '<', $text || die "cannot read: $text"; +for my $adoc (<*.adoc>) { + open I, '<', $adoc || die "cannot read: $adoc"; while (<I>) { if (/^include::/) { chomp; s/^include::\s*//; s/\[\]//; s/{build_dir}/${build_dir}/; - $include{$text}{$_} = 1; + $include{$adoc}{$_} = 1; $included{$_} = 1; } } @@ -23,14 +23,14 @@ for my $text (<*.txt>) { my $changed = 1; while ($changed) { $changed = 0; - while (my ($text, $included) = each %include) { + while (my ($adoc, $included) = each %include) { for my $i (keys %$included) { - # $text has include::$i; if $i includes $j - # $text indirectly includes $j. + # $adoc has include::$i; if $i includes $j + # $adoc indirectly includes $j. if (exists $include{$i}) { for my $j (keys %{$include{$i}}) { - if (!exists $include{$text}{$j}) { - $include{$text}{$j} = 1; + if (!exists $include{$adoc}{$j}) { + $include{$adoc}{$j} = 1; $included{$j} = 1; $changed = 1; } @@ -40,10 +40,10 @@ while ($changed) { } } -foreach my $text (sort keys %include) { - my $included = $include{$text}; - if (! exists $included{$text} && - (my $base = $text) =~ s/\.txt$//) { +foreach my $adoc (sort keys %include) { + my $included = $include{$adoc}; + if (! exists $included{$adoc} && + (my $base = $adoc) =~ s/\.adoc$//) { print "$base.html $base.xml : ", join(" ", sort keys %$included), "\n"; } } diff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl index e260a98977..0a0c1b3f61 100755 --- a/Documentation/cmd-list.perl +++ b/Documentation/cmd-list.perl @@ -5,11 +5,11 @@ use File::Compare qw(compare); sub format_one { my ($source_dir, $out, $nameattr) = @_; my ($name, $attr) = @$nameattr; - my ($path) = "$source_dir/Documentation/$name.txt"; + my ($path) = "$source_dir/Documentation/$name.adoc"; my ($state, $description); my $mansection; $state = 0; - open I, '<', "$path" or die "No such file $path.txt"; + open I, '<', "$path" or die "No such file $path.adoc"; while (<I>) { if (/^(?:git|scalar)[a-z0-9-]*\(([0-9])\)$/) { $mansection = $1; @@ -30,7 +30,7 @@ sub format_one { } close I; if (!defined $description) { - die "No description found in $path.txt"; + die "No description found in $path.adoc"; } if (my ($verify_name, $text) = ($description =~ /^($name) - (.*)/)) { print $out "linkgit:$name\[$mansection\]::\n\t"; @@ -63,7 +63,7 @@ for (sort <IN>) { close IN; for my $out (@categories) { - my ($cat) = $out =~ /^cmds-(.*)\.txt$/; + my ($cat) = $out =~ /^cmds-(.*)\.adoc$/; my ($path) = "$build_dir/$out"; open O, '>', "$path+" or die "Cannot open output file $out+"; for (@{$cmds{$cat}}) { diff --git a/Documentation/config.txt b/Documentation/config.adoc index 8c0b3ed807..cc769251be 100644 --- a/Documentation/config.txt +++ b/Documentation/config.adoc @@ -372,186 +372,188 @@ inventing new variables for use in your own tool, make sure their names do not conflict with those that are used by Git itself and other popular tools, and describe them in your documentation. -include::config/add.txt[] +include::config/add.adoc[] -include::config/advice.txt[] +include::config/advice.adoc[] -include::config/alias.txt[] +include::config/alias.adoc[] -include::config/am.txt[] +include::config/am.adoc[] -include::config/apply.txt[] +include::config/apply.adoc[] -include::config/attr.txt[] +include::config/attr.adoc[] -include::config/bitmap-pseudo-merge.txt[] +include::config/bitmap-pseudo-merge.adoc[] -include::config/blame.txt[] +include::config/blame.adoc[] -include::config/branch.txt[] +include::config/branch.adoc[] -include::config/browser.txt[] +include::config/browser.adoc[] -include::config/bundle.txt[] +include::config/bundle.adoc[] -include::config/checkout.txt[] +include::config/checkout.adoc[] -include::config/clean.txt[] +include::config/clean.adoc[] -include::config/clone.txt[] +include::config/clone.adoc[] -include::config/color.txt[] +include::config/color.adoc[] -include::config/column.txt[] +include::config/column.adoc[] -include::config/commit.txt[] +include::config/commit.adoc[] -include::config/commitgraph.txt[] +include::config/commitgraph.adoc[] -include::config/completion.txt[] +include::config/completion.adoc[] -include::config/core.txt[] +include::config/core.adoc[] -include::config/credential.txt[] +include::config/credential.adoc[] -include::config/diff.txt[] +include::config/diff.adoc[] -include::config/difftool.txt[] +include::config/difftool.adoc[] -include::config/extensions.txt[] +include::config/extensions.adoc[] -include::config/fastimport.txt[] +include::config/fastimport.adoc[] -include::config/feature.txt[] +include::config/feature.adoc[] -include::config/fetch.txt[] +include::config/fetch.adoc[] -include::config/filter.txt[] +include::config/filter.adoc[] -include::config/format.txt[] +include::config/format.adoc[] -include::config/fsck.txt[] +include::config/fsck.adoc[] -include::config/fsmonitor--daemon.txt[] +include::config/fsmonitor--daemon.adoc[] -include::config/gc.txt[] +include::config/gc.adoc[] -include::config/gitcvs.txt[] +include::config/gitcvs.adoc[] -include::config/gitweb.txt[] +include::config/gitweb.adoc[] -include::config/gpg.txt[] +include::config/gpg.adoc[] -include::config/grep.txt[] +include::config/grep.adoc[] -include::config/gui.txt[] +include::config/gui.adoc[] -include::config/guitool.txt[] +include::config/guitool.adoc[] -include::config/help.txt[] +include::config/help.adoc[] -include::config/http.txt[] +include::config/http.adoc[] -include::config/i18n.txt[] +include::config/i18n.adoc[] -include::config/imap.txt[] +include::config/imap.adoc[] -include::config/includeif.txt[] +include::config/includeif.adoc[] -include::config/index.txt[] +include::config/index.adoc[] -include::config/init.txt[] +include::config/init.adoc[] -include::config/instaweb.txt[] +include::config/instaweb.adoc[] -include::config/interactive.txt[] +include::config/interactive.adoc[] -include::config/log.txt[] +include::config/log.adoc[] -include::config/lsrefs.txt[] +include::config/lsrefs.adoc[] -include::config/mailinfo.txt[] +include::config/mailinfo.adoc[] -include::config/mailmap.txt[] +include::config/mailmap.adoc[] -include::config/maintenance.txt[] +include::config/maintenance.adoc[] -include::config/man.txt[] +include::config/man.adoc[] -include::config/merge.txt[] +include::config/merge.adoc[] -include::config/mergetool.txt[] +include::config/mergetool.adoc[] -include::config/notes.txt[] +include::config/notes.adoc[] -include::config/pack.txt[] +include::config/pack.adoc[] -include::config/pager.txt[] +include::config/pager.adoc[] -include::config/pretty.txt[] +include::config/pretty.adoc[] -include::config/promisor.txt[] +include::config/promisor.adoc[] -include::config/protocol.txt[] +include::config/protocol.adoc[] -include::config/pull.txt[] +include::config/pull.adoc[] -include::config/push.txt[] +include::config/push.adoc[] -include::config/rebase.txt[] +include::config/rebase.adoc[] -include::config/receive.txt[] +include::config/receive.adoc[] -include::config/reftable.txt[] +include::config/reftable.adoc[] -include::config/remote.txt[] +include::config/remote.adoc[] -include::config/remotes.txt[] +include::config/remotes.adoc[] -include::config/repack.txt[] +include::config/repack.adoc[] -include::config/rerere.txt[] +include::config/rerere.adoc[] -include::config/revert.txt[] +include::config/revert.adoc[] -include::config/safe.txt[] +include::config/safe.adoc[] -include::config/sendemail.txt[] +include::config/sendemail.adoc[] -include::config/sequencer.txt[] +include::config/sequencer.adoc[] -include::config/showbranch.txt[] +include::config/showbranch.adoc[] -include::config/sparse.txt[] +include::config/sparse.adoc[] -include::config/splitindex.txt[] +include::config/splitindex.adoc[] -include::config/ssh.txt[] +include::config/ssh.adoc[] -include::config/stash.txt[] +include::config/stash.adoc[] -include::config/status.txt[] +include::config/status.adoc[] -include::config/submodule.txt[] +include::config/submodule.adoc[] -include::config/tag.txt[] +include::config/tag.adoc[] -include::config/tar.txt[] +include::config/tar.adoc[] -include::config/trace2.txt[] +include::config/trace2.adoc[] -include::config/transfer.txt[] +include::config/trailer.adoc[] -include::config/uploadarchive.txt[] +include::config/transfer.adoc[] -include::config/uploadpack.txt[] +include::config/uploadarchive.adoc[] -include::config/url.txt[] +include::config/uploadpack.adoc[] -include::config/user.txt[] +include::config/url.adoc[] -include::config/versionsort.txt[] +include::config/user.adoc[] -include::config/web.txt[] +include::config/versionsort.adoc[] -include::config/worktree.txt[] +include::config/web.adoc[] + +include::config/worktree.adoc[] diff --git a/Documentation/config/add.txt b/Documentation/config/add.adoc index 7497533cbc..7497533cbc 100644 --- a/Documentation/config/add.txt +++ b/Documentation/config/add.adoc diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.adoc index 257db58918..257db58918 100644 --- a/Documentation/config/advice.txt +++ b/Documentation/config/advice.adoc diff --git a/Documentation/config/alias.txt b/Documentation/config/alias.adoc index 2c5db0ad84..2c5db0ad84 100644 --- a/Documentation/config/alias.txt +++ b/Documentation/config/alias.adoc diff --git a/Documentation/config/am.txt b/Documentation/config/am.adoc index 5bcad2efb1..5bcad2efb1 100644 --- a/Documentation/config/am.txt +++ b/Documentation/config/am.adoc diff --git a/Documentation/config/apply.txt b/Documentation/config/apply.adoc index f9908e210a..f9908e210a 100644 --- a/Documentation/config/apply.txt +++ b/Documentation/config/apply.adoc diff --git a/Documentation/config/attr.txt b/Documentation/config/attr.adoc index c4a5857993..c4a5857993 100644 --- a/Documentation/config/attr.txt +++ b/Documentation/config/attr.adoc diff --git a/Documentation/config/bitmap-pseudo-merge.txt b/Documentation/config/bitmap-pseudo-merge.adoc index 1f264eca99..1f264eca99 100644 --- a/Documentation/config/bitmap-pseudo-merge.txt +++ b/Documentation/config/bitmap-pseudo-merge.adoc diff --git a/Documentation/config/blame.txt b/Documentation/config/blame.adoc index 4d047c1790..4d047c1790 100644 --- a/Documentation/config/blame.txt +++ b/Documentation/config/blame.adoc diff --git a/Documentation/config/branch.txt b/Documentation/config/branch.adoc index 432b9cd2c0..432b9cd2c0 100644 --- a/Documentation/config/branch.txt +++ b/Documentation/config/branch.adoc diff --git a/Documentation/config/browser.txt b/Documentation/config/browser.adoc index 195df207a6..195df207a6 100644 --- a/Documentation/config/browser.txt +++ b/Documentation/config/browser.adoc diff --git a/Documentation/config/bundle.txt b/Documentation/config/bundle.adoc index 3faae38685..3faae38685 100644 --- a/Documentation/config/bundle.txt +++ b/Documentation/config/bundle.adoc diff --git a/Documentation/config/checkout.txt b/Documentation/config/checkout.adoc index a323022993..a323022993 100644 --- a/Documentation/config/checkout.txt +++ b/Documentation/config/checkout.adoc diff --git a/Documentation/config/clean.txt b/Documentation/config/clean.adoc index c0188ead4e..c0188ead4e 100644 --- a/Documentation/config/clean.txt +++ b/Documentation/config/clean.adoc diff --git a/Documentation/config/clone.txt b/Documentation/config/clone.adoc index 0a10efd174..0a10efd174 100644 --- a/Documentation/config/clone.txt +++ b/Documentation/config/clone.adoc diff --git a/Documentation/config/color.txt b/Documentation/config/color.adoc index 2f2275ac69..2f2275ac69 100644 --- a/Documentation/config/color.txt +++ b/Documentation/config/color.adoc diff --git a/Documentation/config/column.txt b/Documentation/config/column.adoc index 01e4198429..01e4198429 100644 --- a/Documentation/config/column.txt +++ b/Documentation/config/column.adoc diff --git a/Documentation/config/commit.txt b/Documentation/config/commit.adoc index 62f0d92fda..d3f4624fd2 100644 --- a/Documentation/config/commit.txt +++ b/Documentation/config/commit.adoc @@ -1,29 +1,34 @@ -commit.cleanup:: +ifdef::git-commit[] +:see-git-commit: +endif::git-commit[] +ifndef::git-commit[] +:see-git-commit: See linkgit:git-commit[1] for details. +endif::git-commit[] +`commit.cleanup`:: This setting overrides the default of the `--cleanup` option in - `git commit`. See linkgit:git-commit[1] for details. Changing the - default can be useful when you always want to keep lines that begin + `git commit`. {see-git-commit} Changing the default can be useful + when you always want to keep lines that begin with the comment character `#` in your log message, in which case you would do `git config commit.cleanup whitespace` (note that you will have to remove the help lines that begin with `#` in the commit log template yourself, if you do this). -commit.gpgSign:: - +`commit.gpgSign`:: A boolean to specify whether all commits should be GPG signed. Use of this option when doing operations such as rebase can result in a large number of commits being signed. It may be convenient to use an agent to avoid typing your GPG passphrase several times. -commit.status:: +`commit.status`:: A boolean to enable/disable inclusion of status information in the commit message template when using an editor to prepare the commit - message. Defaults to true. + message. Defaults to `true`. -commit.template:: +`commit.template`:: Specify the pathname of a file to use as the template for new commit messages. -commit.verbose:: +`commit.verbose`:: A boolean or int to specify the level of verbosity with `git commit`. - See linkgit:git-commit[1]. + {see-git-commit} diff --git a/Documentation/config/commitgraph.txt b/Documentation/config/commitgraph.adoc index 7f8c9d6638..7f8c9d6638 100644 --- a/Documentation/config/commitgraph.txt +++ b/Documentation/config/commitgraph.adoc diff --git a/Documentation/config/completion.txt b/Documentation/config/completion.adoc index 4d99bf33c9..4d99bf33c9 100644 --- a/Documentation/config/completion.txt +++ b/Documentation/config/completion.adoc diff --git a/Documentation/config/core.txt b/Documentation/config/core.adoc index 8f6d8e7754..8f6d8e7754 100644 --- a/Documentation/config/core.txt +++ b/Documentation/config/core.adoc diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.adoc index 80a7c77772..80a7c77772 100644 --- a/Documentation/config/credential.txt +++ b/Documentation/config/credential.adoc diff --git a/Documentation/config/diff.txt b/Documentation/config/diff.adoc index fdae13a212..1135a62a0a 100644 --- a/Documentation/config/diff.txt +++ b/Documentation/config/diff.adoc @@ -218,8 +218,6 @@ endif::git-diff[] Set this option to `true` to make the diff driver cache the text conversion outputs. See linkgit:gitattributes[5] for details. -include::{build_dir}/mergetools-diff.txt[] - `diff.indentHeuristic`:: Set this option to `false` to disable the default heuristics that shift diff hunk boundaries to make patches easier to read. diff --git a/Documentation/config/difftool.txt b/Documentation/config/difftool.adoc index 447c40d85a..4f7d40ce24 100644 --- a/Documentation/config/difftool.txt +++ b/Documentation/config/difftool.adoc @@ -13,6 +13,8 @@ diff.guitool:: and requires that a corresponding difftool.<guitool>.cmd variable is defined. +include::{build_dir}/mergetools-diff.adoc[] + difftool.<tool>.cmd:: Specify the command to invoke the specified diff tool. The specified command is evaluated in shell with the following diff --git a/Documentation/config/extensions.txt b/Documentation/config/extensions.adoc index 5cb4721a0e..9e2f321a6d 100644 --- a/Documentation/config/extensions.txt +++ b/Documentation/config/extensions.adoc @@ -56,7 +56,7 @@ For historical reasons, this extension is respected regardless of the refStorage:: Specify the ref storage format to use. The acceptable values are: + -include::../ref-storage-format.txt[] +include::../ref-storage-format.adoc[] + Note that this setting should only be set by linkgit:git-init[1] or diff --git a/Documentation/config/fastimport.txt b/Documentation/config/fastimport.adoc index 903677d7ef..903677d7ef 100644 --- a/Documentation/config/fastimport.txt +++ b/Documentation/config/fastimport.adoc diff --git a/Documentation/config/feature.txt b/Documentation/config/feature.adoc index f061b64b74..f061b64b74 100644 --- a/Documentation/config/feature.txt +++ b/Documentation/config/feature.adoc diff --git a/Documentation/config/fetch.txt b/Documentation/config/fetch.adoc index d7dc461bd1..d7dc461bd1 100644 --- a/Documentation/config/fetch.txt +++ b/Documentation/config/fetch.adoc diff --git a/Documentation/config/filter.txt b/Documentation/config/filter.adoc index 90dfe0ba5a..90dfe0ba5a 100644 --- a/Documentation/config/filter.txt +++ b/Documentation/config/filter.adoc diff --git a/Documentation/config/fmt-merge-msg.txt b/Documentation/config/fmt-merge-msg.adoc index 3fbf40e24f..3fbf40e24f 100644 --- a/Documentation/config/fmt-merge-msg.txt +++ b/Documentation/config/fmt-merge-msg.adoc diff --git a/Documentation/config/format.txt b/Documentation/config/format.adoc index 7410e930e5..7410e930e5 100644 --- a/Documentation/config/format.txt +++ b/Documentation/config/format.adoc diff --git a/Documentation/config/fsck.txt b/Documentation/config/fsck.adoc index 8e9e508933..8e9e508933 100644 --- a/Documentation/config/fsck.txt +++ b/Documentation/config/fsck.adoc diff --git a/Documentation/config/fsmonitor--daemon.txt b/Documentation/config/fsmonitor--daemon.adoc index 671f9b9462..671f9b9462 100644 --- a/Documentation/config/fsmonitor--daemon.txt +++ b/Documentation/config/fsmonitor--daemon.adoc diff --git a/Documentation/config/gc.txt b/Documentation/config/gc.adoc index 21d56db279..21d56db279 100644 --- a/Documentation/config/gc.txt +++ b/Documentation/config/gc.adoc diff --git a/Documentation/config/gitcvs.txt b/Documentation/config/gitcvs.adoc index 02da427fd9..02da427fd9 100644 --- a/Documentation/config/gitcvs.txt +++ b/Documentation/config/gitcvs.adoc diff --git a/Documentation/config/gitweb.txt b/Documentation/config/gitweb.adoc index 1b51475108..1b51475108 100644 --- a/Documentation/config/gitweb.txt +++ b/Documentation/config/gitweb.adoc diff --git a/Documentation/config/gpg.txt b/Documentation/config/gpg.adoc index 5cf32b179d..5cf32b179d 100644 --- a/Documentation/config/gpg.txt +++ b/Documentation/config/gpg.adoc diff --git a/Documentation/config/grep.txt b/Documentation/config/grep.adoc index 10041f27b0..10041f27b0 100644 --- a/Documentation/config/grep.txt +++ b/Documentation/config/grep.adoc diff --git a/Documentation/config/gui.txt b/Documentation/config/gui.adoc index 171be774d2..171be774d2 100644 --- a/Documentation/config/gui.txt +++ b/Documentation/config/gui.adoc diff --git a/Documentation/config/guitool.txt b/Documentation/config/guitool.adoc index 43fb9466ff..43fb9466ff 100644 --- a/Documentation/config/guitool.txt +++ b/Documentation/config/guitool.adoc diff --git a/Documentation/config/help.txt b/Documentation/config/help.adoc index 610701f9a3..b369589cec 100644 --- a/Documentation/config/help.txt +++ b/Documentation/config/help.adoc @@ -11,13 +11,14 @@ help.autoCorrect:: If git detects typos and can identify exactly one valid command similar to the error, git will try to suggest the correct command or even run the suggestion automatically. Possible config values are: - - 0 (default): show the suggested command. - - positive number: run the suggested command after specified + - 0, "false", "off", "no", "show": show the suggested command (default). + - 1, "true", "on", "yes", "immediate": run the suggested command +immediately. + - positive number > 1: run the suggested command after specified deciseconds (0.1 sec). - - "immediate": run the suggested command immediately. + - "never": don't run or show any suggested command. - "prompt": show the suggestion and prompt for confirmation to run the command. - - "never": don't run or show any suggested command. help.htmlPath:: Specify the path where the HTML documentation resides. File system paths diff --git a/Documentation/config/http.txt b/Documentation/config/http.adoc index a14371b5c9..22a8803dea 100644 --- a/Documentation/config/http.txt +++ b/Documentation/config/http.adoc @@ -216,6 +216,21 @@ http.sslBackend:: This option is ignored if cURL lacks support for choosing the SSL backend at runtime. +http.sslCertType:: + Type of client certificate used when fetching or pushing over HTTPS. + "PEM", "DER" are supported when using openssl or gnutls backends. "P12" + is supported on "openssl", "schannel", "securetransport", and gnutls 8.11+. + See also libcurl `CURLOPT_SSLCERTTYPE`. Can be overridden by the + `GIT_SSL_CERT_TYPE` environment variable. + +http.sslKeyType:: + Type of client private key used when fetching or pushing over HTTPS. (e.g. + "PEM", "DER", or "ENG"). Only applicable when using "openssl" backend. "DER" + is not supported with openssl. Particularly useful when set to "ENG" for + authenticating with PKCS#11 tokens, with a PKCS#11 URL in sslCert option. + See also libcurl `CURLOPT_SSLKEYTYPE`. Can be overridden by the + `GIT_SSL_KEY_TYPE` environment variable. + http.schannelCheckRevoke:: Used to enforce or disable certificate revocation checks in cURL when http.sslBackend is set to "schannel". Defaults to `true` if diff --git a/Documentation/config/i18n.txt b/Documentation/config/i18n.adoc index 6e72fdb45b..6e72fdb45b 100644 --- a/Documentation/config/i18n.txt +++ b/Documentation/config/i18n.adoc diff --git a/Documentation/config/imap.txt b/Documentation/config/imap.adoc index 3d28f72643..3d28f72643 100644 --- a/Documentation/config/imap.txt +++ b/Documentation/config/imap.adoc diff --git a/Documentation/config/includeif.txt b/Documentation/config/includeif.adoc index 82fe431c34..82fe431c34 100644 --- a/Documentation/config/includeif.txt +++ b/Documentation/config/includeif.adoc diff --git a/Documentation/config/index.txt b/Documentation/config/index.adoc index 3eff420360..3eff420360 100644 --- a/Documentation/config/index.txt +++ b/Documentation/config/index.adoc diff --git a/Documentation/config/init.txt b/Documentation/config/init.adoc index e45b2a8121..e45b2a8121 100644 --- a/Documentation/config/init.txt +++ b/Documentation/config/init.adoc diff --git a/Documentation/config/instaweb.txt b/Documentation/config/instaweb.adoc index 50cb2f7d62..50cb2f7d62 100644 --- a/Documentation/config/instaweb.txt +++ b/Documentation/config/instaweb.adoc diff --git a/Documentation/config/interactive.txt b/Documentation/config/interactive.adoc index 8b876cb4eb..8b876cb4eb 100644 --- a/Documentation/config/interactive.txt +++ b/Documentation/config/interactive.adoc diff --git a/Documentation/config/log.txt b/Documentation/config/log.adoc index 9003a82191..9003a82191 100644 --- a/Documentation/config/log.txt +++ b/Documentation/config/log.adoc diff --git a/Documentation/config/lsrefs.txt b/Documentation/config/lsrefs.adoc index 3d88fb0bad..3d88fb0bad 100644 --- a/Documentation/config/lsrefs.txt +++ b/Documentation/config/lsrefs.adoc diff --git a/Documentation/config/mailinfo.txt b/Documentation/config/mailinfo.adoc index ec3a5d81f7..ec3a5d81f7 100644 --- a/Documentation/config/mailinfo.txt +++ b/Documentation/config/mailinfo.adoc diff --git a/Documentation/config/mailmap.txt b/Documentation/config/mailmap.adoc index 48cbc30722..48cbc30722 100644 --- a/Documentation/config/mailmap.txt +++ b/Documentation/config/mailmap.adoc diff --git a/Documentation/config/maintenance.txt b/Documentation/config/maintenance.adoc index 72a9d6cf81..72a9d6cf81 100644 --- a/Documentation/config/maintenance.txt +++ b/Documentation/config/maintenance.adoc diff --git a/Documentation/config/man.txt b/Documentation/config/man.adoc index 5a0f82cc23..5a0f82cc23 100644 --- a/Documentation/config/man.txt +++ b/Documentation/config/man.adoc diff --git a/Documentation/config/merge.txt b/Documentation/config/merge.adoc index 82554d65a0..d2d0f21a71 100644 --- a/Documentation/config/merge.txt +++ b/Documentation/config/merge.adoc @@ -37,7 +37,7 @@ merge.verifySignatures:: If true, this is equivalent to the --verify-signatures command line option. See linkgit:git-merge[1] for details. -include::fmt-merge-msg.txt[] +include::fmt-merge-msg.adoc[] merge.renameLimit:: The number of files to consider in the exhaustive portion of @@ -69,7 +69,8 @@ merge.renormalize:: Tell Git that canonical representation of files in the repository has changed over time (e.g. earlier commits record text files with CRLF line endings, but recent ones use LF line - endings). In such a repository, Git can convert the data + endings). In such a repository, for each file where a + three-way content merge is needed, Git can convert the data recorded in commits to a canonical form before performing a merge to reduce unnecessary conflicts. For more information, see section "Merging branches with differing checkin/checkout @@ -101,7 +102,7 @@ merge.guitool:: Any other value is treated as a custom merge tool and requires that a corresponding mergetool.<guitool>.cmd variable is defined. -include::{build_dir}/mergetools-merge.txt[] +include::{build_dir}/mergetools-merge.adoc[] merge.verbosity:: Controls the amount of output shown by the recursive merge diff --git a/Documentation/config/mergetool.txt b/Documentation/config/mergetool.adoc index 00bf665aa0..00bf665aa0 100644 --- a/Documentation/config/mergetool.txt +++ b/Documentation/config/mergetool.adoc diff --git a/Documentation/config/notes.txt b/Documentation/config/notes.adoc index 43db8e808d..b7e536496f 100644 --- a/Documentation/config/notes.txt +++ b/Documentation/config/notes.adoc @@ -1,4 +1,4 @@ -notes.mergeStrategy:: +`notes.mergeStrategy`:: Which merge strategy to choose by default when resolving notes conflicts. Must be one of `manual`, `ours`, `theirs`, `union`, or `cat_sort_uniq`. Defaults to `manual`. See the "NOTES MERGE STRATEGIES" @@ -7,17 +7,17 @@ notes.mergeStrategy:: This setting can be overridden by passing the `--strategy` option to linkgit:git-notes[1]. -notes.<name>.mergeStrategy:: +`notes.<name>.mergeStrategy`:: Which merge strategy to choose when doing a notes merge into - refs/notes/<name>. This overrides the more general - "notes.mergeStrategy". See the "NOTES MERGE STRATEGIES" section in + `refs/notes/<name>`. This overrides the more general + `notes.mergeStrategy`. See the "NOTES MERGE STRATEGIES" section in linkgit:git-notes[1] for more information on the available strategies. -notes.displayRef:: +`notes.displayRef`:: Which ref (or refs, if a glob or specified more than once), in addition to the default set by `core.notesRef` or `GIT_NOTES_REF`, to read notes from when showing commit - messages with the 'git log' family of commands. + messages with the `git log` family of commands. + This setting can be overridden with the `GIT_NOTES_DISPLAY_REF` environment variable, which must be a colon separated list of refs or @@ -26,27 +26,27 @@ globs. A warning will be issued for refs that do not exist, but a glob that does not match any refs is silently ignored. + -This setting can be disabled by the `--no-notes` option to the 'git -log' family of commands, or by the `--notes=<ref>` option accepted by +This setting can be disabled by the `--no-notes` option to the linkgit:git-log[1] +family of commands, or by the `--notes=<ref>` option accepted by those commands. + -The effective value of "core.notesRef" (possibly overridden by -GIT_NOTES_REF) is also implicitly added to the list of refs to be +The effective value of `core.notesRef` (possibly overridden by +`GIT_NOTES_REF`) is also implicitly added to the list of refs to be displayed. -notes.rewrite.<command>:: - When rewriting commits with <command> (currently `amend` or +`notes.rewrite.<command>`:: + When rewriting commits with _<command>_ (currently `amend` or `rebase`), if this variable is `false`, git will not copy notes from the original to the rewritten commit. Defaults to - `true`. See also "`notes.rewriteRef`" below. + `true`. See also `notes.rewriteRef` below. + This setting can be overridden with the `GIT_NOTES_REWRITE_REF` environment variable, which must be a colon separated list of refs or globs. -notes.rewriteMode:: +`notes.rewriteMode`:: When copying notes during a rewrite (see the - "notes.rewrite.<command>" option), determines what to do if + `notes.rewrite.<command>` option), determines what to do if the target commit already has a note. Must be one of `overwrite`, `concatenate`, `cat_sort_uniq`, or `ignore`. Defaults to `concatenate`. @@ -54,7 +54,7 @@ notes.rewriteMode:: This setting can be overridden with the `GIT_NOTES_REWRITE_MODE` environment variable. -notes.rewriteRef:: +`notes.rewriteRef`:: When copying notes during a rewrite, specifies the (fully qualified) ref whose notes should be copied. May be a glob, in which case notes in all matching refs will be copied. You diff --git a/Documentation/config/pack.txt b/Documentation/config/pack.adoc index da527377fa..da527377fa 100644 --- a/Documentation/config/pack.txt +++ b/Documentation/config/pack.adoc diff --git a/Documentation/config/pager.txt b/Documentation/config/pager.adoc index d3731cf66c..d3731cf66c 100644 --- a/Documentation/config/pager.txt +++ b/Documentation/config/pager.adoc diff --git a/Documentation/config/pretty.txt b/Documentation/config/pretty.adoc index 063c6b63d9..063c6b63d9 100644 --- a/Documentation/config/pretty.txt +++ b/Documentation/config/pretty.adoc diff --git a/Documentation/config/promisor.adoc b/Documentation/config/promisor.adoc new file mode 100644 index 0000000000..9192acfd24 --- /dev/null +++ b/Documentation/config/promisor.adoc @@ -0,0 +1,30 @@ +promisor.quiet:: + If set to "true" assume `--quiet` when fetching additional + objects for a partial clone. + +promisor.advertise:: + If set to "true", a server will use the "promisor-remote" + capability, see linkgit:gitprotocol-v2[5], to advertise the + promisor remotes it is using, if it uses some. Default is + "false", which means the "promisor-remote" capability is not + advertised. + +promisor.acceptFromServer:: + If set to "all", a client will accept all the promisor remotes + a server might advertise using the "promisor-remote" + capability. If set to "knownName" the client will accept + promisor remotes which are already configured on the client + and have the same name as those advertised by the client. This + is not very secure, but could be used in a corporate setup + where servers and clients are trusted to not switch name and + URLs. If set to "knownUrl", the client will accept promisor + remotes which have both the same name and the same URL + configured on the client as the name and URL advertised by the + server. This is more secure than "all" or "knownName", so it + should be used if possible instead of those options. Default + is "none", which means no promisor remote advertised by a + server will be accepted. By accepting a promisor remote, the + client agrees that the server might omit objects that are + lazily fetchable from this promisor remote from its responses + to "fetch" and "clone" requests from the client. See + linkgit:gitprotocol-v2[5]. diff --git a/Documentation/config/promisor.txt b/Documentation/config/promisor.txt deleted file mode 100644 index 98c5cb2ec2..0000000000 --- a/Documentation/config/promisor.txt +++ /dev/null @@ -1,3 +0,0 @@ -promisor.quiet:: - If set to "true" assume `--quiet` when fetching additional - objects for a partial clone. diff --git a/Documentation/config/protocol.txt b/Documentation/config/protocol.adoc index a9bf187a93..a9bf187a93 100644 --- a/Documentation/config/protocol.txt +++ b/Documentation/config/protocol.adoc diff --git a/Documentation/config/pull.txt b/Documentation/config/pull.adoc index 9349e09261..9349e09261 100644 --- a/Documentation/config/pull.txt +++ b/Documentation/config/pull.adoc diff --git a/Documentation/config/push.txt b/Documentation/config/push.adoc index 0acbbea18a..0acbbea18a 100644 --- a/Documentation/config/push.txt +++ b/Documentation/config/push.adoc diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.adoc index c6187ab28b..c6187ab28b 100644 --- a/Documentation/config/rebase.txt +++ b/Documentation/config/rebase.adoc diff --git a/Documentation/config/receive.txt b/Documentation/config/receive.adoc index 36a1e6f2d2..36a1e6f2d2 100644 --- a/Documentation/config/receive.txt +++ b/Documentation/config/receive.adoc diff --git a/Documentation/config/reftable.txt b/Documentation/config/reftable.adoc index 57087803a5..57087803a5 100644 --- a/Documentation/config/reftable.txt +++ b/Documentation/config/reftable.adoc diff --git a/Documentation/config/remote.txt b/Documentation/config/remote.adoc index 4118c219c1..25fe219d10 100644 --- a/Documentation/config/remote.txt +++ b/Documentation/config/remote.adoc @@ -101,21 +101,21 @@ remote.<name>.serverOption:: The default set of server options used when fetching from this remote. These server options can be overridden by the `--server-option=` command line arguments. ++ +This is a multi-valued variable, and an empty value can be used in a higher +priority configuration file (e.g. `.git/config` in a repository) to clear +the values inherited from a lower priority configuration files (e.g. +`$HOME/.gitconfig`). remote.<name>.followRemoteHEAD:: How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD`. The default value is "create", which will create `remotes/<name>/HEAD` - if it exists on the remote, but not locally, but will not touch an - already existing local reference. Setting to "warn" will print - a message if the remote has a different value, than the local one and + if it exists on the remote, but not locally; this will not touch an + already existing local reference. Setting it to "warn" will print + a message if the remote has a different value than the local one; in case there is no local reference, it behaves like "create". A variant on "warn" is "warn-if-not-$branch", which behaves like "warn", but if `HEAD` on the remote is `$branch` it will be silent. - Setting to "always" will silently update it to the value on the remote. - Finally, setting it to "never" will never change or create the local - reference. -+ -This is a multi-valued variable, and an empty value can be used in a higher -priority configuration file (e.g. `.git/config` in a repository) to clear -the values inherited from a lower priority configuration files (e.g. -`$HOME/.gitconfig`). + Setting it to "always" will silently update `remotes/<name>/HEAD` to + the value on the remote. Finally, setting it to "never" will never + change or create the local reference. diff --git a/Documentation/config/remotes.txt b/Documentation/config/remotes.adoc index 4cfe03221e..4cfe03221e 100644 --- a/Documentation/config/remotes.txt +++ b/Documentation/config/remotes.adoc diff --git a/Documentation/config/repack.txt b/Documentation/config/repack.adoc index c79af6d7b8..c79af6d7b8 100644 --- a/Documentation/config/repack.txt +++ b/Documentation/config/repack.adoc diff --git a/Documentation/config/rerere.txt b/Documentation/config/rerere.adoc index 3a78b5ebb1..3a78b5ebb1 100644 --- a/Documentation/config/rerere.txt +++ b/Documentation/config/rerere.adoc diff --git a/Documentation/config/revert.txt b/Documentation/config/revert.adoc index 802d6faca2..802d6faca2 100644 --- a/Documentation/config/revert.txt +++ b/Documentation/config/revert.adoc diff --git a/Documentation/config/safe.txt b/Documentation/config/safe.adoc index 2d45c98b12..2d45c98b12 100644 --- a/Documentation/config/safe.txt +++ b/Documentation/config/safe.adoc diff --git a/Documentation/config/sendemail.txt b/Documentation/config/sendemail.adoc index 5ffcfc9f2a..5ffcfc9f2a 100644 --- a/Documentation/config/sendemail.txt +++ b/Documentation/config/sendemail.adoc diff --git a/Documentation/config/sequencer.txt b/Documentation/config/sequencer.adoc index e664eef01d..e664eef01d 100644 --- a/Documentation/config/sequencer.txt +++ b/Documentation/config/sequencer.adoc diff --git a/Documentation/config/showbranch.txt b/Documentation/config/showbranch.adoc index e79ecd9ee9..e79ecd9ee9 100644 --- a/Documentation/config/showbranch.txt +++ b/Documentation/config/showbranch.adoc diff --git a/Documentation/config/sparse.txt b/Documentation/config/sparse.adoc index aff49a8d3a..aff49a8d3a 100644 --- a/Documentation/config/sparse.txt +++ b/Documentation/config/sparse.adoc diff --git a/Documentation/config/splitindex.txt b/Documentation/config/splitindex.adoc index cfaa29610b..cfaa29610b 100644 --- a/Documentation/config/splitindex.txt +++ b/Documentation/config/splitindex.adoc diff --git a/Documentation/config/ssh.txt b/Documentation/config/ssh.adoc index 2ca4bf93e1..2ca4bf93e1 100644 --- a/Documentation/config/ssh.txt +++ b/Documentation/config/ssh.adoc diff --git a/Documentation/config/stash.txt b/Documentation/config/stash.adoc index ec1edaeba6..ec1edaeba6 100644 --- a/Documentation/config/stash.txt +++ b/Documentation/config/stash.adoc diff --git a/Documentation/config/status.txt b/Documentation/config/status.adoc index 8caf90f51c..8caf90f51c 100644 --- a/Documentation/config/status.txt +++ b/Documentation/config/status.adoc diff --git a/Documentation/config/submodule.txt b/Documentation/config/submodule.adoc index 0672d99117..0672d99117 100644 --- a/Documentation/config/submodule.txt +++ b/Documentation/config/submodule.adoc diff --git a/Documentation/config/tag.txt b/Documentation/config/tag.adoc index 5062a057ff..5062a057ff 100644 --- a/Documentation/config/tag.txt +++ b/Documentation/config/tag.adoc diff --git a/Documentation/config/tar.txt b/Documentation/config/tar.adoc index de8ff48ea9..de8ff48ea9 100644 --- a/Documentation/config/tar.txt +++ b/Documentation/config/tar.adoc diff --git a/Documentation/config/trace2.txt b/Documentation/config/trace2.adoc index 3b6bca2b7a..05639ce33f 100644 --- a/Documentation/config/trace2.txt +++ b/Documentation/config/trace2.adoc @@ -17,7 +17,7 @@ trace2.eventTarget:: It may be overridden by the `GIT_TRACE2_EVENT` environment variable. The following table shows possible values. + -include::../trace2-target-values.txt[] +include::../trace2-target-values.adoc[] trace2.normalBrief:: Boolean. When true `time`, `filename`, and `line` fields are diff --git a/Documentation/config/trailer.adoc b/Documentation/config/trailer.adoc new file mode 100644 index 0000000000..60bc221c88 --- /dev/null +++ b/Documentation/config/trailer.adoc @@ -0,0 +1,136 @@ +trailer.separators:: + This option tells which characters are recognized as trailer + separators. By default only ':' is recognized as a trailer + separator, except that '=' is always accepted on the command + line for compatibility with other git commands. ++ +The first character given by this option will be the default character +used when another separator is not specified in the config for this +trailer. ++ +For example, if the value for this option is "%=$", then only lines +using the format '<key><sep><value>' with <sep> containing '%', '=' +or '$' and then spaces will be considered trailers. And '%' will be +the default separator used, so by default trailers will appear like: +'<key>% <value>' (one percent sign and one space will appear between +the key and the value). + +trailer.where:: + This option tells where a new trailer will be added. ++ +This can be `end`, which is the default, `start`, `after` or `before`. ++ +If it is `end`, then each new trailer will appear at the end of the +existing trailers. ++ +If it is `start`, then each new trailer will appear at the start, +instead of the end, of the existing trailers. ++ +If it is `after`, then each new trailer will appear just after the +last trailer with the same <key>. ++ +If it is `before`, then each new trailer will appear just before the +first trailer with the same <key>. + +trailer.ifexists:: + This option makes it possible to choose what action will be + performed when there is already at least one trailer with the + same <key> in the input. ++ +The valid values for this option are: `addIfDifferentNeighbor` (this +is the default), `addIfDifferent`, `add`, `replace` or `doNothing`. ++ +With `addIfDifferentNeighbor`, a new trailer will be added only if no +trailer with the same (<key>, <value>) pair is above or below the line +where the new trailer will be added. ++ +With `addIfDifferent`, a new trailer will be added only if no trailer +with the same (<key>, <value>) pair is already in the input. ++ +With `add`, a new trailer will be added, even if some trailers with +the same (<key>, <value>) pair are already in the input. ++ +With `replace`, an existing trailer with the same <key> will be +deleted and the new trailer will be added. The deleted trailer will be +the closest one (with the same <key>) to the place where the new one +will be added. ++ +With `doNothing`, nothing will be done; that is no new trailer will be +added if there is already one with the same <key> in the input. + +trailer.ifmissing:: + This option makes it possible to choose what action will be + performed when there is not yet any trailer with the same + <key> in the input. ++ +The valid values for this option are: `add` (this is the default) and +`doNothing`. ++ +With `add`, a new trailer will be added. ++ +With `doNothing`, nothing will be done. + +trailer.<keyAlias>.key:: + Defines a <keyAlias> for the <key>. The <keyAlias> must be a + prefix (case does not matter) of the <key>. For example, in `git + config trailer.ack.key "Acked-by"` the "Acked-by" is the <key> and + the "ack" is the <keyAlias>. This configuration allows the shorter + `--trailer "ack:..."` invocation on the command line using the "ack" + <keyAlias> instead of the longer `--trailer "Acked-by:..."`. ++ +At the end of the <key>, a separator can appear and then some +space characters. By default the only valid separator is ':', +but this can be changed using the `trailer.separators` config +variable. ++ +If there is a separator in the key, then it overrides the default +separator when adding the trailer. + +trailer.<keyAlias>.where:: + This option takes the same values as the 'trailer.where' + configuration variable and it overrides what is specified by + that option for trailers with the specified <keyAlias>. + +trailer.<keyAlias>.ifexists:: + This option takes the same values as the 'trailer.ifexists' + configuration variable and it overrides what is specified by + that option for trailers with the specified <keyAlias>. + +trailer.<keyAlias>.ifmissing:: + This option takes the same values as the 'trailer.ifmissing' + configuration variable and it overrides what is specified by + that option for trailers with the specified <keyAlias>. + +trailer.<keyAlias>.command:: + Deprecated in favor of 'trailer.<keyAlias>.cmd'. + This option behaves in the same way as 'trailer.<keyAlias>.cmd', except + that it doesn't pass anything as argument to the specified command. + Instead the first occurrence of substring $ARG is replaced by the + <value> that would be passed as argument. ++ +Note that $ARG in the user's command is +only replaced once and that the original way of replacing $ARG is not safe. ++ +When both 'trailer.<keyAlias>.cmd' and 'trailer.<keyAlias>.command' are given +for the same <keyAlias>, 'trailer.<keyAlias>.cmd' is used and +'trailer.<keyAlias>.command' is ignored. + +trailer.<keyAlias>.cmd:: + This option can be used to specify a shell command that will be called + once to automatically add a trailer with the specified <keyAlias>, and then + called each time a '--trailer <keyAlias>=<value>' argument is specified to + modify the <value> of the trailer that this option would produce. ++ +When the specified command is first called to add a trailer +with the specified <keyAlias>, the behavior is as if a special +'--trailer <keyAlias>=<value>' argument was added at the beginning +of the "git interpret-trailers" command, where <value> +is taken to be the standard output of the command with any +leading and trailing whitespace trimmed off. ++ +If some '--trailer <keyAlias>=<value>' arguments are also passed +on the command line, the command is called again once for each +of these arguments with the same <keyAlias>. And the <value> part +of these arguments, if any, will be passed to the command as its +first argument. This way the command can produce a <value> computed +from the <value> passed in the '--trailer <keyAlias>=<value>' argument. diff --git a/Documentation/config/transfer.txt b/Documentation/config/transfer.adoc index f1ce50f4a6..f1ce50f4a6 100644 --- a/Documentation/config/transfer.txt +++ b/Documentation/config/transfer.adoc diff --git a/Documentation/config/uploadarchive.txt b/Documentation/config/uploadarchive.adoc index e0698e8c1d..e0698e8c1d 100644 --- a/Documentation/config/uploadarchive.txt +++ b/Documentation/config/uploadarchive.adoc diff --git a/Documentation/config/uploadpack.txt b/Documentation/config/uploadpack.adoc index 0e1dda944a..0e1dda944a 100644 --- a/Documentation/config/uploadpack.txt +++ b/Documentation/config/uploadpack.adoc diff --git a/Documentation/config/url.txt b/Documentation/config/url.adoc index e5566c371d..e5566c371d 100644 --- a/Documentation/config/url.txt +++ b/Documentation/config/url.adoc diff --git a/Documentation/config/user.txt b/Documentation/config/user.adoc index 2ffc38d164..2ffc38d164 100644 --- a/Documentation/config/user.txt +++ b/Documentation/config/user.adoc diff --git a/Documentation/config/versionsort.txt b/Documentation/config/versionsort.adoc index 0cff090819..0cff090819 100644 --- a/Documentation/config/versionsort.txt +++ b/Documentation/config/versionsort.adoc diff --git a/Documentation/config/web.txt b/Documentation/config/web.adoc index beec8d1303..beec8d1303 100644 --- a/Documentation/config/web.txt +++ b/Documentation/config/web.adoc diff --git a/Documentation/config/worktree.txt b/Documentation/config/worktree.adoc index 5e35c7d018..5e35c7d018 100644 --- a/Documentation/config/worktree.txt +++ b/Documentation/config/worktree.adoc diff --git a/Documentation/date-formats.txt b/Documentation/date-formats.adoc index e24517c496..e24517c496 100644 --- a/Documentation/date-formats.txt +++ b/Documentation/date-formats.adoc diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.adoc index c72fb37986..80e36e153d 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.adoc @@ -121,7 +121,7 @@ Note that 'combined diff' lists only files which were modified from all parents. -include::diff-generate-patch.txt[] +include::diff-generate-patch.adoc[] other diff formats diff --git a/Documentation/diff-generate-patch.txt b/Documentation/diff-generate-patch.adoc index e5c813c96f..e5c813c96f 100644 --- a/Documentation/diff-generate-patch.txt +++ b/Documentation/diff-generate-patch.adoc diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.adoc index 640eb6e7db..640eb6e7db 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.adoc diff --git a/Documentation/everyday.txto b/Documentation/everyday.adoco index ae555bd47e..ae555bd47e 100644 --- a/Documentation/everyday.txto +++ b/Documentation/everyday.adoco diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.adoc index b01372e4b3..b01372e4b3 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.adoc diff --git a/Documentation/fsck-msgids.txt b/Documentation/fsck-msgids.adoc index b14bc44ca4..9601fff228 100644 --- a/Documentation/fsck-msgids.txt +++ b/Documentation/fsck-msgids.adoc @@ -16,6 +16,13 @@ `badObjectSha1`:: (ERROR) An object has a bad sha1. +`badPackedRefEntry`:: + (ERROR) The "packed-refs" file contains an invalid entry. + +`badPackedRefHeader`:: + (ERROR) The "packed-refs" file contains an invalid + header. + `badParentSha1`:: (ERROR) A commit object has a bad parent sha1. @@ -176,6 +183,13 @@ `nullSha1`:: (WARN) Tree contains entries pointing to a null sha1. +`packedRefEntryNotTerminated`:: + (ERROR) The "packed-refs" file contains an entry that is + not terminated by a newline. + +`packedRefUnsorted`:: + (ERROR) The "packed-refs" file is not sorted. + `refMissingNewline`:: (INFO) A loose ref that does not end with newline(LF). As valid implementations of Git never created such a loose ref diff --git a/Documentation/git-add.txt b/Documentation/git-add.adoc index 5f2c3592b8..eba0b419ce 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.adoc @@ -437,10 +437,10 @@ they will make the patch impossible to apply: CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] :git-add: 1 -include::config/add.txt[] +include::config/add.adoc[] SEE ALSO -------- diff --git a/Documentation/git-am.txt b/Documentation/git-am.adoc index 69d5cc9f21..221070de48 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.adoc @@ -120,7 +120,7 @@ default. You can use `--no-utf8` to override this. am.threeWay configuration variable. For more information, see am.threeWay in linkgit:git-config[1]. -include::rerere-options.txt[] +include::rerere-options.adoc[] --ignore-space-change:: --ignore-whitespace:: @@ -284,9 +284,9 @@ information. CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/am.txt[] +include::config/am.adoc[] SEE ALSO -------- diff --git a/Documentation/git-annotate.txt b/Documentation/git-annotate.adoc index 5ae8aabe0f..965bc676af 100644 --- a/Documentation/git-annotate.txt +++ b/Documentation/git-annotate.adoc @@ -22,7 +22,7 @@ familiar command name for people coming from other SCM systems. OPTIONS ------- -include::blame-options.txt[] +include::blame-options.adoc[] SEE ALSO -------- diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.adoc index dd4a61ef28..952518b8af 100644 --- a/Documentation/git-apply.txt +++ b/Documentation/git-apply.adoc @@ -270,9 +270,9 @@ has no effect when `--index` or `--cached` is in use. CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/apply.txt[] +include::config/apply.adoc[] SUBMODULES ---------- diff --git a/Documentation/git-archimport.txt b/Documentation/git-archimport.adoc index 847777fd17..847777fd17 100644 --- a/Documentation/git-archimport.txt +++ b/Documentation/git-archimport.adoc diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.adoc index a0e3fe7996..a0e3fe7996 100644 --- a/Documentation/git-archive.txt +++ b/Documentation/git-archive.adoc diff --git a/Documentation/git-backfill.adoc b/Documentation/git-backfill.adoc new file mode 100644 index 0000000000..95623051f7 --- /dev/null +++ b/Documentation/git-backfill.adoc @@ -0,0 +1,71 @@ +git-backfill(1) +=============== + +NAME +---- +git-backfill - Download missing objects in a partial clone + + +SYNOPSIS +-------- +[synopsis] +git backfill [--min-batch-size=<n>] [--[no-]sparse] + +DESCRIPTION +----------- + +Blobless partial clones are created using `git clone --filter=blob:none` +and then configure the local repository such that the Git client avoids +downloading blob objects unless they are required for a local operation. +This initially means that the clone and later fetches download reachable +commits and trees but no blobs. Later operations that change the `HEAD` +pointer, such as `git checkout` or `git merge`, may need to download +missing blobs in order to complete their operation. + +In the worst cases, commands that compute blob diffs, such as `git blame`, +become very slow as they download the missing blobs in single-blob +requests to satisfy the missing object as the Git command needs it. This +leads to multiple download requests and no ability for the Git server to +provide delta compression across those objects. + +The `git backfill` command provides a way for the user to request that +Git downloads the missing blobs (with optional filters) such that the +missing blobs representing historical versions of files can be downloaded +in batches. The `backfill` command attempts to optimize the request by +grouping blobs that appear at the same path, hopefully leading to good +delta compression in the packfile sent by the server. + +In this way, `git backfill` provides a mechanism to break a large clone +into smaller chunks. Starting with a blobless partial clone with `git +clone --filter=blob:none` and then running `git backfill` in the local +repository provides a way to download all reachable objects in several +smaller network calls than downloading the entire repository at clone +time. + +By default, `git backfill` downloads all blobs reachable from the `HEAD` +commit. This set can be restricted or expanded using various options. + +THIS COMMAND IS EXPERIMENTAL. ITS BEHAVIOR MAY CHANGE IN THE FUTURE. + + +OPTIONS +------- + +`--min-batch-size=<n>`:: + Specify a minimum size for a batch of missing objects to request + from the server. This size may be exceeded by the last set of + blobs seen at a given path. The default minimum batch size is + 50,000. + +`--[no-]sparse`:: + Only download objects if they appear at a path that matches the + current sparse-checkout. If the sparse-checkout feature is enabled, + then `--sparse` is assumed and can be disabled with `--no-sparse`. + +SEE ALSO +-------- +linkgit:git-clone[1]. + +GIT +--- +Part of the linkgit:git[1] suite diff --git a/Documentation/git-bisect-lk2009.txt b/Documentation/git-bisect-lk2009.adoc index 0bc165788e..0bc165788e 100644 --- a/Documentation/git-bisect-lk2009.txt +++ b/Documentation/git-bisect-lk2009.adoc diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.adoc index 82f944dc03..58dbb74a15 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.adoc @@ -495,6 +495,7 @@ $ git bisect old HEAD~10 # the tenth commit from now is marked as old ------------ + or: ++ ------------ $ git bisect start --term-old broken --term-new fixed $ git bisect fixed diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.adoc index b1d7fb539d..f75ed44790 100644 --- a/Documentation/git-blame.txt +++ b/Documentation/git-blame.adoc @@ -48,7 +48,7 @@ ea4c7f9bf69e781dd0cd88d2bccb2bf5cc15c9a7 git-blame: Make the output OPTIONS ------- -include::blame-options.txt[] +include::blame-options.adoc[] -c:: Use the same output mode as linkgit:git-annotate[1] (Default: off). @@ -244,9 +244,9 @@ See linkgit:gitmailmap[5]. CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/blame.txt[] +include::config/blame.adoc[] SEE ALSO -------- diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.adoc index 0b08442932..7a073a36d6 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.adoc @@ -345,9 +345,9 @@ CONFIGURATION `--list` is used or implied. The default is to use a pager. See linkgit:git-config[1]. -include::includes/cmd-config-section-rest.txt[] +include::includes/cmd-config-section-rest.adoc[] -include::config/branch.txt[] +include::config/branch.adoc[] EXAMPLES -------- @@ -415,7 +415,7 @@ serve four related but different purposes: - `--no-merged` is used to find branches which are candidates for merging into HEAD, since those branches are not fully contained by HEAD. -include::ref-reachability-filters.txt[] +include::ref-reachability-filters.adoc[] SEE ALSO -------- diff --git a/Documentation/git-bugreport.txt b/Documentation/git-bugreport.adoc index 112658b3c3..112658b3c3 100644 --- a/Documentation/git-bugreport.txt +++ b/Documentation/git-bugreport.adoc diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.adoc index 03cd36fe8d..03cd36fe8d 100644 --- a/Documentation/git-bundle.txt +++ b/Documentation/git-bundle.adoc diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.adoc index d5890ae368..30359f5dbd 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.adoc @@ -322,10 +322,10 @@ of `%(objectsize)` bytes), followed by a newline. For example, `--batch` without a custom format would produce: ------------- +----------- <oid> SP <type> SP <size> LF <contents> LF ------------- +----------- Whereas `--batch-check='%(objectname) %(objecttype)'` would produce: diff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.adoc index cb5a6c8f33..503b644657 100644 --- a/Documentation/git-check-attr.txt +++ b/Documentation/git-check-attr.adoc @@ -76,6 +76,7 @@ EXAMPLES -------- In the examples, the following '.gitattributes' file is used: + --------------- *.java diff=java -crlf myAttr NoMyAttr.java !myAttr @@ -83,12 +84,14 @@ README caveat=unspecified --------------- * Listing a single attribute: ++ --------------- $ git check-attr diff org/example/MyClass.java org/example/MyClass.java: diff: java --------------- * Listing multiple attributes for a file: ++ --------------- $ git check-attr crlf diff myAttr -- org/example/MyClass.java org/example/MyClass.java: crlf: unset @@ -97,6 +100,7 @@ org/example/MyClass.java: myAttr: set --------------- * Listing all attributes for a file: ++ --------------- $ git check-attr --all -- org/example/MyClass.java org/example/MyClass.java: diff: java @@ -104,6 +108,7 @@ org/example/MyClass.java: myAttr: set --------------- * Listing an attribute for multiple files: ++ --------------- $ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java org/example/MyClass.java: myAttr: set @@ -111,6 +116,7 @@ org/example/NoMyAttr.java: myAttr: unspecified --------------- * Not all values are equally unambiguous: ++ --------------- $ git check-attr caveat README README: caveat: unspecified diff --git a/Documentation/git-check-ignore.txt b/Documentation/git-check-ignore.adoc index 3e3b4e3446..3e3b4e3446 100644 --- a/Documentation/git-check-ignore.txt +++ b/Documentation/git-check-ignore.adoc diff --git a/Documentation/git-check-mailmap.txt b/Documentation/git-check-mailmap.adoc index 966c91c46a..966c91c46a 100644 --- a/Documentation/git-check-mailmap.txt +++ b/Documentation/git-check-mailmap.adoc diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.adoc index 2aacfd1808..2aacfd1808 100644 --- a/Documentation/git-check-ref-format.txt +++ b/Documentation/git-check-ref-format.adoc diff --git a/Documentation/git-checkout-index.txt b/Documentation/git-checkout-index.adoc index faf8d6ca36..faf8d6ca36 100644 --- a/Documentation/git-checkout-index.txt +++ b/Documentation/git-checkout-index.adoc diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.adoc index bf26655764..a66c53a5cd 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.adoc @@ -612,9 +612,9 @@ $ git add frotz CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/checkout.txt[] +include::config/checkout.adoc[] SEE ALSO -------- diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.adoc index 81ace900fc..42b41923d5 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.adoc @@ -172,11 +172,11 @@ fail unless one of `--empty=keep` or `--allow-empty` are specified. Pass the merge strategy-specific option through to the merge strategy. See linkgit:git-merge[1] for details. -include::rerere-options.txt[] +include::rerere-options.adoc[] SEQUENCER SUBCOMMANDS --------------------- -include::sequencer.txt[] +include::sequencer.adoc[] EXAMPLES -------- diff --git a/Documentation/git-cherry.txt b/Documentation/git-cherry.adoc index 0ea921a593..0ea921a593 100644 --- a/Documentation/git-cherry.txt +++ b/Documentation/git-cherry.adoc diff --git a/Documentation/git-citool.txt b/Documentation/git-citool.adoc index c7a11c36c1..c7a11c36c1 100644 --- a/Documentation/git-citool.txt +++ b/Documentation/git-citool.adoc diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.adoc index fd17165416..bed52c203b 100644 --- a/Documentation/git-clean.txt +++ b/Documentation/git-clean.adoc @@ -140,9 +140,9 @@ help:: CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/clean.txt[] +include::config/clean.adoc[] SEE ALSO -------- diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.adoc index de8d8f5893..222d558290 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.adoc @@ -13,7 +13,7 @@ git clone [--template=<template-directory>] [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror] [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>] [--dissociate] [--separate-git-dir <git-dir>] - [--depth <depth>] [--[no-]single-branch] [--no-tags] + [--depth <depth>] [--[no-]single-branch] [--[no-]tags] [--recurse-submodules[=<pathspec>]] [--[no-]shallow-submodules] [--[no-]remote-submodules] [--jobs <n>] [--sparse] [--[no-]reject-shallow] [--filter=<filter-spec>] [--also-filter-submodules]] [--] <repository> @@ -221,6 +221,15 @@ objects from the source repository into a pack in the cloned repository. `--branch` can also take tags and detaches the `HEAD` at that commit in the resulting repository. +`--revision=<rev>`:: + Create a new repository, and fetch the history leading to the given + revision _<rev>_ (and nothing else), without making any remote-tracking + branch, and without making any local branch, and detach `HEAD` to + _<rev>_. The argument can be a ref name (e.g. `refs/heads/main` or + `refs/tags/v1.0`) that peels down to a commit, or a hexadecimal object + name. + This option is incompatible with `--branch` and `--mirror`. + `-u` _<upload-pack>_:: `--upload-pack` _<upload-pack>_:: When given, and the repository to clone from is accessed @@ -273,12 +282,15 @@ corresponding `--mirror` and `--no-tags` options instead. branch when `--single-branch` clone was made, no remote-tracking branch is created. -`--no-tags`:: - Don't clone any tags, and set - `remote.<remote>.tagOpt=--no-tags` in the config, ensuring - that future `git pull` and `git fetch` operations won't follow - any tags. Subsequent explicit tag fetches will still work, - (see linkgit:git-fetch[1]). +`--[no-]tags`:: + Control whether or not tags will be cloned. When `--no-tags` is + given, the option will be become permanent by setting the + `remote.<remote>.tagOpt=--no-tags` configuration. This ensures that + future `git pull` and `git fetch` won't follow any tags. Subsequent + explicit tag fetches will still work (see linkgit:git-fetch[1]). ++ +By default, tags are cloned and passing `--tags` is thus typically a +no-op, unless it cancels out a previous `--no-tags`. + Can be used in conjunction with `--single-branch` to clone and maintain a branch with no references other than a single cloned @@ -321,7 +333,7 @@ or `--mirror` is given) Specify the given ref storage format for the repository. The valid values are: + -include::ref-storage-format.txt[] +include::ref-storage-format.adoc[] `-j` _<n>_:: `--jobs` _<n>_:: @@ -348,7 +360,7 @@ _<directory>_:: `--shallow-since`, and `--shallow-exclude`. :git-clone: 1 -include::urls.txt[] +include::urls.adoc[] EXAMPLES -------- @@ -396,11 +408,11 @@ $ git clone --no-local /home/otheruser/proj.git /pub/scm/proj.git CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/init.txt[] +include::config/init.adoc[] -include::config/clone.txt[] +include::config/clone.adoc[] GIT diff --git a/Documentation/git-column.txt b/Documentation/git-column.adoc index 18431647a2..5a4f2b6fde 100644 --- a/Documentation/git-column.txt +++ b/Documentation/git-column.adoc @@ -50,6 +50,7 @@ EXAMPLES -------- Format data by columns: ++ ------------ $ seq 1 24 | git column --mode=column --padding=5 1 4 7 10 13 16 19 22 @@ -58,6 +59,7 @@ $ seq 1 24 | git column --mode=column --padding=5 ------------ Format data by rows: ++ ------------ $ seq 1 21 | git column --mode=row --padding=5 1 2 3 4 5 6 7 @@ -66,6 +68,7 @@ $ seq 1 21 | git column --mode=row --padding=5 ------------ List some tags in a table with unequal column widths: ++ ------------ $ git tag --list 'v2.4.*' --column=row,dense v2.4.0 v2.4.0-rc0 v2.4.0-rc1 v2.4.0-rc2 v2.4.0-rc3 @@ -77,9 +80,9 @@ v2.4.8 v2.4.9 CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/column.txt[] +include::config/column.adoc[] GIT --- diff --git a/Documentation/git-commit-graph.txt b/Documentation/git-commit-graph.adoc index 903b16830e..50b5016804 100644 --- a/Documentation/git-commit-graph.txt +++ b/Documentation/git-commit-graph.adoc @@ -148,9 +148,9 @@ $ git rev-parse HEAD | git commit-graph write --stdin-commits --append CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/commitgraph.txt[] +include::config/commitgraph.adoc[] FILE FORMAT diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.adoc index 2e2c581098..6472921e14 100644 --- a/Documentation/git-commit-tree.txt +++ b/Documentation/git-commit-tree.adoc @@ -80,12 +80,12 @@ A commit comment is read from stdin. If a changelog entry is not provided via "<" redirection, 'git commit-tree' will just wait for one to be entered and terminated with ^D. -include::date-formats.txt[] +include::date-formats.adoc[] Discussion ---------- -include::i18n.txt[] +include::i18n.adoc[] FILES ----- diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.adoc index c822113c11..dc219025f1 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.adoc @@ -7,8 +7,8 @@ git-commit - Record changes to the repository SYNOPSIS -------- -[verse] -'git commit' [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend] +[synopsis] +git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend] [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|reword):]<commit>] [-F <file> | -m <msg>] [--reset-author] [--allow-empty] [--allow-empty-message] [--no-verify] [-e] [--author=<author>] @@ -23,31 +23,31 @@ Create a new commit containing the current contents of the index and the given log message describing the changes. The new commit is a direct child of HEAD, usually the tip of the current branch, and the branch is updated to point to it (unless no branch is associated with -the working tree, in which case HEAD is "detached" as described in +the working tree, in which case `HEAD` is "detached" as described in linkgit:git-checkout[1]). The content to be committed can be specified in several ways: 1. by using linkgit:git-add[1] to incrementally "add" changes to the - index before using the 'commit' command (Note: even modified files + index before using the `commit` command (Note: even modified files must be "added"); 2. by using linkgit:git-rm[1] to remove files from the working tree - and the index, again before using the 'commit' command; + and the index, again before using the `commit` command; -3. by listing files as arguments to the 'commit' command - (without --interactive or --patch switch), in which +3. by listing files as arguments to the `commit` command + (without `--interactive` or `--patch` switch), in which case the commit will ignore changes staged in the index, and instead record the current content of the listed files (which must already be known to Git); -4. by using the -a switch with the 'commit' command to automatically +4. by using the `-a` switch with the `commit` command to automatically "add" changes from all known files (i.e. all files that are already listed in the index) and to automatically "rm" files in the index that have been removed from the working tree, and then perform the actual commit; -5. by using the --interactive or --patch switches with the 'commit' command +5. by using the `--interactive` or `--patch` switches with the `commit` command to decide one by one which files or hunks should be part of the commit in addition to contents in the index, before finalizing the operation. See the ``Interactive Mode'' section of @@ -58,139 +58,139 @@ summary of what is included by any of the above for the next commit by giving the same set of parameters (options and paths). If you make a commit and then find a mistake immediately after -that, you can recover from it with 'git reset'. +that, you can recover from it with `git reset`. :git-commit: 1 OPTIONS ------- --a:: ---all:: - Tell the command to automatically stage files that have +`-a`:: +`--all`:: + Automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected. --p:: ---patch:: +`-p`:: +`--patch`:: Use the interactive patch selection interface to choose which changes to commit. See linkgit:git-add[1] for details. --C <commit>:: ---reuse-message=<commit>:: - Take an existing commit object, and reuse the log message +`-C <commit>`:: +`--reuse-message=<commit>`:: + Take an existing _<commit>_ object, and reuse the log message and the authorship information (including the timestamp) when creating the commit. --c <commit>:: ---reedit-message=<commit>:: - Like '-C', but with `-c` the editor is invoked, so that +`-c <commit>`:: +`--reedit-message=<commit>`:: + Like `-C`, but with `-c` the editor is invoked, so that the user can further edit the commit message. ---fixup=[(amend|reword):]<commit>:: - Create a new commit which "fixes up" `<commit>` when applied with +`--fixup=[(amend|reword):]<commit>`:: + Create a new commit which "fixes up" _<commit>_ when applied with `git rebase --autosquash`. Plain `--fixup=<commit>` creates a - "fixup!" commit which changes the content of `<commit>` but leaves + "fixup!" commit which changes the content of _<commit>_ but leaves its log message untouched. `--fixup=amend:<commit>` is similar but creates an "amend!" commit which also replaces the log message of - `<commit>` with the log message of the "amend!" commit. + _<commit>_ with the log message of the "amend!" commit. `--fixup=reword:<commit>` creates an "amend!" commit which - replaces the log message of `<commit>` with its own log message - but makes no changes to the content of `<commit>`. + replaces the log message of _<commit>_ with its own log message + but makes no changes to the content of _<commit>_. + -The commit created by plain `--fixup=<commit>` has a subject -composed of "fixup!" followed by the subject line from <commit>, +The commit created by plain `--fixup=<commit>` has a title +composed of "fixup!" followed by the title of _<commit>_, and is recognized specially by `git rebase --autosquash`. The `-m` option may be used to supplement the log message of the created commit, but the additional commentary will be thrown away once the -"fixup!" commit is squashed into `<commit>` by +"fixup!" commit is squashed into _<commit>_ by `git rebase --autosquash`. + The commit created by `--fixup=amend:<commit>` is similar but its -subject is instead prefixed with "amend!". The log message of -<commit> is copied into the log message of the "amend!" commit and +title is instead prefixed with "amend!". The log message of +_<commit>_ is copied into the log message of the "amend!" commit and opened in an editor so it can be refined. When `git rebase ---autosquash` squashes the "amend!" commit into `<commit>`, the -log message of `<commit>` is replaced by the refined log message +--autosquash` squashes the "amend!" commit into _<commit>_, the +log message of _<commit>_ is replaced by the refined log message from the "amend!" commit. It is an error for the "amend!" commit's log message to be empty unless `--allow-empty-message` is specified. + `--fixup=reword:<commit>` is shorthand for `--fixup=amend:<commit> ---only`. It creates an "amend!" commit with only a log message + --only`. It creates an "amend!" commit with only a log message (ignoring any changes staged in the index). When squashed by `git -rebase --autosquash`, it replaces the log message of `<commit>` +rebase --autosquash`, it replaces the log message of _<commit>_ without making any other changes. + Neither "fixup!" nor "amend!" commits change authorship of -`<commit>` when applied by `git rebase --autosquash`. +_<commit>_ when applied by `git rebase --autosquash`. See linkgit:git-rebase[1] for details. ---squash=<commit>:: - Construct a commit message for use with `rebase --autosquash`. - The commit message subject line is taken from the specified +`--squash=<commit>`:: + Construct a commit message for use with `git rebase --autosquash`. + The commit message title is taken from the specified commit with a prefix of "squash! ". Can be used with additional commit message options (`-m`/`-c`/`-C`/`-F`). See linkgit:git-rebase[1] for details. ---reset-author:: - When used with -C/-c/--amend options, or when committing after a +`--reset-author`:: + When used with `-C`/`-c`/`--amend` options, or when committing after a conflicting cherry-pick, declare that the authorship of the resulting commit now belongs to the committer. This also renews the author timestamp. ---short:: +`--short`:: When doing a dry-run, give the output in the short-format. See linkgit:git-status[1] for details. Implies `--dry-run`. ---branch:: +`--branch`:: Show the branch and tracking info even in short-format. ---porcelain:: +`--porcelain`:: When doing a dry-run, give the output in a porcelain-ready format. See linkgit:git-status[1] for details. Implies `--dry-run`. ---long:: +`--long`:: When doing a dry-run, give the output in the long-format. Implies `--dry-run`. --z:: ---null:: +`-z`:: +`--null`:: When showing `short` or `porcelain` status output, print the - filename verbatim and terminate the entries with NUL, instead of LF. + filename verbatim and terminate the entries with _NUL_, instead of _LF_. If no format is given, implies the `--porcelain` output format. Without the `-z` option, filenames with "unusual" characters are quoted as explained for the configuration variable `core.quotePath` (see linkgit:git-config[1]). --F <file>:: ---file=<file>:: - Take the commit message from the given file. Use '-' to +`-F <file>`:: +`--file=<file>`:: + Take the commit message from _<file>_. Use '-' to read the message from the standard input. ---author=<author>:: +`--author=<author>`:: Override the commit author. Specify an explicit author using the - standard `A U Thor <author@example.com>` format. Otherwise <author> + standard `A U Thor <author@example.com>` format. Otherwise _<author>_ is assumed to be a pattern and is used to search for an existing - commit by that author (i.e. rev-list --all -i --author=<author>); + commit by that author (i.e. `git rev-list --all -i --author=<author>`); the commit author is then copied from the first such commit found. ---date=<date>:: +`--date=<date>`:: Override the author date used in the commit. --m <msg>:: ---message=<msg>:: - Use the given <msg> as the commit message. +`-m <msg>`:: +`--message=<msg>`:: + Use _<msg>_ as the commit message. If multiple `-m` options are given, their values are concatenated as separate paragraphs. + The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`. --t <file>:: ---template=<file>:: +`-t <file>`:: +`--template=<file>`:: When editing the commit message, start the editor with the - contents in the given file. The `commit.template` configuration + contents in _<file>_. The `commit.template` configuration variable is often used to give this option implicitly to the command. This mechanism can be used by projects that want to guide participants with some hints on what to write in the message @@ -198,58 +198,56 @@ The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`. message, the commit is aborted. This has no effect when a message is given by other means, e.g. with the `-m` or `-F` options. -include::signoff-option.txt[] +include::signoff-option.adoc[] ---trailer <token>[(=|:)<value>]:: - Specify a (<token>, <value>) pair that should be applied as a +`--trailer <token>[(=|:)<value>]`:: + Specify a (_<token>_, _<value>_) pair that should be applied as a trailer. (e.g. `git commit --trailer "Signed-off-by:C O Mitter \ <committer@example.com>" --trailer "Helped-by:C O Mitter \ - <committer@example.com>"` will add the "Signed-off-by" trailer - and the "Helped-by" trailer to the commit message.) + <committer@example.com>"` will add the `Signed-off-by` trailer + and the `Helped-by` trailer to the commit message.) The `trailer.*` configuration variables (linkgit:git-interpret-trailers[1]) can be used to define if a duplicated trailer is omitted, where in the run of trailers each trailer would appear, and other details. --n:: ---[no-]verify:: - By default, the pre-commit and commit-msg hooks are run. - When any of `--no-verify` or `-n` is given, these are bypassed. +`-n`:: +`--[no-]verify`:: + Bypass the `pre-commit` and `commit-msg` hooks. See also linkgit:githooks[5]. ---allow-empty:: +`--allow-empty`:: Usually recording a commit that has the exact same tree as its sole parent commit is a mistake, and the command prevents you from making such a commit. This option bypasses the safety, and is primarily for use by foreign SCM interface scripts. ---allow-empty-message:: - Like --allow-empty this command is primarily for use by foreign - SCM interface scripts. It allows you to create a commit with an - empty commit message without using plumbing commands like - linkgit:git-commit-tree[1]. +`--allow-empty-message`:: + Create a commit with an empty commit message without using plumbing + commands like linkgit:git-commit-tree[1]. Like `--allow-empty`, this + command is primarily for use by foreign SCM interface scripts. ---cleanup=<mode>:: - This option determines how the supplied commit message should be +`--cleanup=<mode>`:: + Determine how the supplied commit message should be cleaned up before committing. The '<mode>' can be `strip`, `whitespace`, `verbatim`, `scissors` or `default`. + -- -strip:: +`strip`:: Strip leading and trailing empty lines, trailing whitespace, commentary and collapse consecutive empty lines. -whitespace:: +`whitespace`:: Same as `strip` except #commentary is not removed. -verbatim:: +`verbatim`:: Do not change the message at all. -scissors:: +`scissors`:: Same as `whitespace` except that everything from (and including) the line found below is truncated, if the message is to be edited. - "`#`" can be customized with core.commentChar. + "`#`" can be customized with `core.commentChar`. # ------------------------ >8 ------------------------ -default:: +`default`:: Same as `strip` if the message is to be edited. Otherwise `whitespace`. -- @@ -257,19 +255,18 @@ default:: The default can be changed by the `commit.cleanup` configuration variable (see linkgit:git-config[1]). --e:: ---edit:: - The message taken from file with `-F`, command line with - `-m`, and from commit object with `-C` are usually used as - the commit log message unmodified. This option lets you - further edit the message taken from these sources. +`-e`:: +`--edit`:: + Let the user further edit the message taken from _<file>_ + with `-F <file>`, command line with `-m <message>`, and + from _<commit>_ with `-C <commit>`. ---no-edit:: +`--no-edit`:: Use the selected commit message without launching an editor. For example, `git commit --amend --no-edit` amends a commit without changing its commit message. ---amend:: +`--amend`:: Replace the tip of the current branch by creating a new commit. The recorded tree is prepared as usual (including the effect of the `-i` and `-o` options and explicit @@ -295,23 +292,23 @@ You should understand the implications of rewriting history if you amend a commit that has already been published. (See the "RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].) ---no-post-rewrite:: - Bypass the post-rewrite hook. +`--no-post-rewrite`:: + Bypass the `post-rewrite` hook. --i:: ---include:: +`-i`:: +`--include`:: Before making a commit out of staged contents so far, stage the contents of paths given on the command line as well. This is usually not what you want unless you are concluding a conflicted merge. --o:: ---only:: +`-o`:: +`--only`:: Make a commit by taking the updated working tree contents of the paths specified on the command line, disregarding any contents that have been staged for other paths. This is the default mode of operation of - 'git commit' if any paths are given on the command line, + `git commit` if any paths are given on the command line, in which case this option can be omitted. If this option is specified together with `--amend`, then no paths need to be specified, which can be used to amend @@ -319,48 +316,48 @@ FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].) already been staged. If used together with `--allow-empty` paths are also not required, and an empty commit will be created. ---pathspec-from-file=<file>:: - Pathspec is passed in `<file>` instead of commandline args. If - `<file>` is exactly `-` then standard input is used. Pathspec - elements are separated by LF or CR/LF. Pathspec elements can be +`--pathspec-from-file=<file>`:: + Pass pathspec in _<file>_ instead of commandline args. If + _<file>_ is exactly `-` then standard input is used. Pathspec + elements are separated by _LF_ or _CR_/_LF_. Pathspec elements can be quoted as explained for the configuration variable `core.quotePath` (see linkgit:git-config[1]). See also `--pathspec-file-nul` and global `--literal-pathspecs`. ---pathspec-file-nul:: +`--pathspec-file-nul`:: Only meaningful with `--pathspec-from-file`. Pathspec elements are - separated with NUL character and all other characters are taken + separated with _NUL_ character and all other characters are taken literally (including newlines and quotes). --u[<mode>]:: ---untracked-files[=<mode>]:: +`-u[<mode>]`:: +`--untracked-files[=<mode>]`:: Show untracked files. + -- -The mode parameter is optional (defaults to 'all'), and is used to -specify the handling of untracked files; when -u is not used, the -default is 'normal', i.e. show untracked files and directories. +The _<mode>_ parameter is optional (defaults to `all`), and is used to +specify the handling of untracked files; when `-u` is not used, the +default is `normal`, i.e. show untracked files and directories. The possible options are: - - 'no' - Show no untracked files - - 'normal' - Shows untracked files and directories - - 'all' - Also shows individual files in untracked directories. +`no`:: Show no untracked files +`normal`:: Shows untracked files and directories +`all`:: Also shows individual files in untracked directories. All usual spellings for Boolean value `true` are taken as `normal` and `false` as `no`. -The default can be changed using the status.showUntrackedFiles +The default can be changed using the `status.showUntrackedFiles` configuration variable documented in linkgit:git-config[1]. -- --v:: ---verbose:: - Show unified diff between the HEAD commit and what +`-v`:: +`--verbose`:: + Show unified diff between the `HEAD` commit and what would be committed at the bottom of the commit message template to help the user describe the commit by reminding what changes the commit has. Note that this diff output doesn't have its - lines prefixed with '#'. This diff will not be a part + lines prefixed with `#`. This diff will not be a part of the commit message. See the `commit.verbose` configuration variable in linkgit:git-config[1]. + @@ -368,40 +365,40 @@ If specified twice, show in addition the unified diff between what would be committed and the worktree files, i.e. the unstaged changes to tracked files. --q:: ---quiet:: +`-q`:: +`--quiet`:: Suppress commit summary message. ---dry-run:: +`--dry-run`:: Do not create a commit, but show a list of paths that are to be committed, paths with local changes that will be left uncommitted and paths that are untracked. ---status:: +`--status`:: Include the output of linkgit:git-status[1] in the commit message template when using an editor to prepare the commit message. Defaults to on, but can be used to override - configuration variable commit.status. + configuration variable `commit.status`. ---no-status:: +`--no-status`:: Do not include the output of linkgit:git-status[1] in the commit message template when using an editor to prepare the default commit message. --S[<keyid>]:: ---gpg-sign[=<keyid>]:: ---no-gpg-sign:: - GPG-sign commits. The `keyid` argument is optional and +`-S[<key-id>]`:: +`--gpg-sign[=<key-id>]`:: +`--no-gpg-sign`:: + GPG-sign commits. The _<key-id>_ is optional and defaults to the committer identity; if specified, it must be stuck to the option without a space. `--no-gpg-sign` is useful to countermand both `commit.gpgSign` configuration variable, and earlier `--gpg-sign`. -\--:: +`--`:: Do not interpret any more arguments as options. -<pathspec>...:: - When pathspec is given on the command line, commit the contents of +`<pathspec>...`:: + When _<pathspec>_ is given on the command line, commit the contents of the files that match the pathspec without recording the changes already added to the index. The contents of these files are also staged for the next commit on top of what have been staged before. @@ -412,10 +409,10 @@ EXAMPLES -------- When recording your own work, the contents of modified files in your working tree are temporarily stored to a staging area -called the "index" with 'git add'. A file can be +called the "index" with `git add`. A file can be reverted back, only in the index but not in the working tree, to that of the last commit with `git restore --staged <file>`, -which effectively reverts 'git add' and prevents the changes to +which effectively reverts `git add` and prevents the changes to this file from participating in the next commit. After building the state to be committed incrementally with these commands, `git commit` (without any pathname parameter) is used to record what @@ -443,7 +440,7 @@ $ git commit -a ------------ The command `git commit -a` first looks at your working tree, -notices that you have modified hello.c and removed goodbye.c, +notices that you have modified `hello.c` and removed `goodbye.c`, and performs necessary `git add` and `git rm` for you. After staging changes to many files, you can alter the order the @@ -471,13 +468,13 @@ $ git commit this second commit would record the changes to `hello.c` and `hello.h` as expected. -After a merge (initiated by 'git merge' or 'git pull') stops +After a merge (initiated by `git merge` or `git pull`) stops because of conflicts, cleanly merged paths are already staged to be committed for you, and paths that conflicted are left in unmerged state. You would have to first -check which paths are conflicting with 'git status' +check which paths are conflicting with `git status` and after fixing them manually in your working tree, you would -stage the result as usual with 'git add': +stage the result as usual with `git add`: ------------ $ git status | grep unmerged @@ -507,12 +504,12 @@ COMMIT INFORMATION Author and committer information is taken from the following environment variables, if set: - GIT_AUTHOR_NAME - GIT_AUTHOR_EMAIL - GIT_AUTHOR_DATE - GIT_COMMITTER_NAME - GIT_COMMITTER_EMAIL - GIT_COMMITTER_DATE + * `GIT_AUTHOR_NAME` + * `GIT_AUTHOR_EMAIL` + * `GIT_AUTHOR_DATE` + * `GIT_COMMITTER_NAME` + * `GIT_COMMITTER_EMAIL` + * `GIT_COMMITTER_DATE` (nb "<", ">" and "\n"s are stripped) @@ -524,7 +521,7 @@ that, see the `credential.username` variable in linkgit:git-config[1]. In case (some of) these environment variables are not set, the information is taken from the configuration items `user.name` and `user.email`, or, if not -present, the environment variable EMAIL, or, if that is not set, +present, the environment variable `EMAIL`, or, if that is not set, system user name and the hostname used for outgoing mail (taken from `/etc/mailname` and falling back to the fully qualified hostname when that file does not exist). @@ -537,7 +534,7 @@ The typical usage is to set just the `user.name` and `user.email` variables; the other options are provided for more complex use cases. :git-commit: 1 -include::date-formats.txt[] +include::date-formats.adoc[] DISCUSSION ---------- @@ -550,18 +547,18 @@ as the commit title, and that title is used throughout Git. For example, linkgit:git-format-patch[1] turns a commit into email, and it uses the title on the Subject line and the rest of the commit in the body. -include::i18n.txt[] +include::i18n.adoc[] ENVIRONMENT AND CONFIGURATION VARIABLES --------------------------------------- The editor used to edit the commit log message will be chosen from the -`GIT_EDITOR` environment variable, the core.editor configuration variable, the +`GIT_EDITOR` environment variable, the `core.editor` configuration variable, the `VISUAL` environment variable, or the `EDITOR` environment variable (in that order). See linkgit:git-var[1] for details. -include::includes/cmd-config-section-rest.txt[] +include::includes/cmd-config-section-rest.adoc[] -include::config/commit.txt[] +include::config/commit.adoc[] HOOKS ----- diff --git a/Documentation/git-config.txt b/Documentation/git-config.adoc index 3e420177c1..936e0c5130 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.adoc @@ -213,7 +213,9 @@ See also <<FILES>>. + Valid `<type>`'s include: + -- 'bool': canonicalize values as either "true" or "false". +- 'bool': canonicalize values `true`, `yes`,`on`, and positive + numbers as "true", and values `false`, `no`, `off` and `0` as + "false". - 'int': canonicalize values as simple decimal numbers. An optional suffix of 'k', 'm', or 'g' will cause the value to be multiplied by 1024, 1048576, or 1073741824 upon input. @@ -610,7 +612,7 @@ http.cookieFile /tmp/cookie.txt http.sslverify false ------------ -include::config.txt[] +include::config.adoc[] BUGS ---- diff --git a/Documentation/git-count-objects.txt b/Documentation/git-count-objects.adoc index 97f9f12610..97f9f12610 100644 --- a/Documentation/git-count-objects.txt +++ b/Documentation/git-count-objects.adoc diff --git a/Documentation/git-credential-cache--daemon.txt b/Documentation/git-credential-cache--daemon.adoc index 650a15a7ed..650a15a7ed 100644 --- a/Documentation/git-credential-cache--daemon.txt +++ b/Documentation/git-credential-cache--daemon.adoc diff --git a/Documentation/git-credential-cache.txt b/Documentation/git-credential-cache.adoc index 487cc557a8..54fa7a27e1 100644 --- a/Documentation/git-credential-cache.txt +++ b/Documentation/git-credential-cache.adoc @@ -78,6 +78,23 @@ variable (this example increases the cache time to 1 hour): $ git config credential.helper 'cache --timeout=3600' ------------------------------------------------------- +PERSONAL ACCESS TOKENS +---------------------- + +Some remotes accept personal access tokens, which are randomly +generated and hard to memorise. They typically have a lifetime of weeks +or months. + +git-credential-cache is inherently unsuitable for persistent storage of +personal access tokens. The credential will be forgotten after the cache +timeout. Even if you configure a long timeout, credentials will be +forgotten if the daemon dies. + +To avoid frequently regenerating personal access tokens, configure a +credential helper with persistent storage. Alternatively, configure an +OAuth credential helper to generate credentials automatically. See +linkgit:gitcredentials[7], sections "Available helpers" and "OAuth". + GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/git-credential-store.txt b/Documentation/git-credential-store.adoc index 71864a8726..71864a8726 100644 --- a/Documentation/git-credential-store.txt +++ b/Documentation/git-credential-store.adoc diff --git a/Documentation/git-credential.txt b/Documentation/git-credential.adoc index e41493292f..e41493292f 100644 --- a/Documentation/git-credential.txt +++ b/Documentation/git-credential.adoc diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.adoc index 41c8a8a05c..41c8a8a05c 100644 --- a/Documentation/git-cvsexportcommit.txt +++ b/Documentation/git-cvsexportcommit.adoc diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.adoc index 90fdc2551a..90fdc2551a 100644 --- a/Documentation/git-cvsimport.txt +++ b/Documentation/git-cvsimport.adoc diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.adoc index 4c475efeab..fe822f571d 100644 --- a/Documentation/git-cvsserver.txt +++ b/Documentation/git-cvsserver.adoc @@ -125,9 +125,11 @@ creation in your platform (e.g. mkpasswd in Linux, encrypt in OpenBSD or pwhash in NetBSD) and paste it in the right location. Then provide your password via the pserver method, for example: + ------ cvs -d:pserver:someuser:somepassword@server:/path/repo.git co <HEAD_name> ------ + No special setup is needed for SSH access, other than having Git tools in the PATH. If you have clients that do not accept the CVS_SERVER environment variable, you can rename 'git-cvsserver' to `cvs`. @@ -138,6 +140,7 @@ CVS_SERVER directly in CVSROOT like ------ cvs -d ":ext;CVS_SERVER=git cvsserver:user@server/path/repo.git" co <HEAD_name> ------ + This has the advantage that it will be saved in your 'CVS/Root' files and you don't need to worry about always setting the correct environment variable. SSH users restricted to 'git-shell' don't need to override the default @@ -168,6 +171,7 @@ All configuration variables can also be overridden for a specific method of access. Valid method names are "ext" (for SSH access) and "pserver". The following example configuration would disable pserver access while still allowing access over SSH. + ------ [gitcvs] enabled=0 diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.adoc index ede7b935d6..ede7b935d6 100644 --- a/Documentation/git-daemon.txt +++ b/Documentation/git-daemon.adoc diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.adoc index 08ff715709..08ff715709 100644 --- a/Documentation/git-describe.txt +++ b/Documentation/git-describe.adoc diff --git a/Documentation/git-diagnose.txt b/Documentation/git-diagnose.adoc index 0711959e6f..0711959e6f 100644 --- a/Documentation/git-diagnose.txt +++ b/Documentation/git-diagnose.adoc diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.adoc index bf78e31431..2b2358ca1c 100644 --- a/Documentation/git-diff-files.txt +++ b/Documentation/git-diff-files.adoc @@ -20,7 +20,7 @@ same as for 'git diff-index' and 'git diff-tree'. OPTIONS ------- -include::diff-options.txt[] +include::diff-options.adoc[] -1 --base:: -2 --ours:: @@ -45,7 +45,7 @@ omit diff output for unmerged entries and just show "Unmerged". Remain silent even for nonexistent files -include::diff-format.txt[] +include::diff-format.adoc[] GIT --- diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.adoc index 4de1d4c8f1..911446a296 100644 --- a/Documentation/git-diff-index.txt +++ b/Documentation/git-diff-index.adoc @@ -21,7 +21,7 @@ files are compared. OPTIONS ------- -include::diff-options.txt[] +include::diff-options.adoc[] <tree-ish>:: The id of a tree object to diff against. @@ -40,7 +40,7 @@ include::diff-options.txt[] 'git diff-index' say that all non-checked-out files are up to date. -include::diff-format.txt[] +include::diff-format.adoc[] OPERATING MODES --------------- diff --git a/Documentation/git-diff-pairs.adoc b/Documentation/git-diff-pairs.adoc new file mode 100644 index 0000000000..f99fcd1ead --- /dev/null +++ b/Documentation/git-diff-pairs.adoc @@ -0,0 +1,60 @@ +git-diff-pairs(1) +================= + +NAME +---- +git-diff-pairs - Compare the content and mode of provided blob pairs + +SYNOPSIS +-------- +[synopsis] +git diff-pairs -z [<diff-options>] + +DESCRIPTION +----------- +Show changes for file pairs provided on stdin. Input for this command must be +in the NUL-terminated raw output format as generated by commands such as `git +diff-tree -z -r --raw`. By default, the outputted diffs are computed and shown +in the patch format when stdin closes. + +A single NUL byte may be written to stdin between raw input lines to compute +file pair diffs up to that point instead of waiting for stdin to close. A NUL +byte is also written to the output to delimit between these batches of diffs. + +Usage of this command enables the traditional diff pipeline to be broken up +into separate stages where `diff-pairs` acts as the output phase. Other +commands, such as `diff-tree`, may serve as a frontend to compute the raw +diff format used as input. + +Instead of computing diffs via `git diff-tree -p -M` in one step, `diff-tree` +can compute the file pairs and rename information without the blob diffs. This +output can be fed to `diff-pairs` to generate the underlying blob diffs as done +in the following example: + +----------------------------- +git diff-tree -z -r -M $a $b | +git diff-pairs -z +----------------------------- + +Computing the tree diff upfront with rename information allows patch output +from `diff-pairs` to be progressively computed over the course of potentially +multiple invocations. + +Pathspecs are not currently supported by `diff-pairs`. Pathspec limiting should +be performed by the upstream command generating the raw diffs used as input. + +Tree objects are not currently supported as input and are rejected. + +Abbreviated object IDs in the `diff-pairs` input are not supported. Outputted +object IDs can be abbreviated using the `--abbrev` option. + +OPTIONS +------- + +include::diff-options.adoc[] + +include::diff-generate-patch.adoc[] + +GIT +--- +Part of the linkgit:git[1] suite diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.adoc index 09286a85eb..f1e3134bde 100644 --- a/Documentation/git-diff-tree.txt +++ b/Documentation/git-diff-tree.adoc @@ -24,7 +24,7 @@ Note that 'git diff-tree' can use the tree encapsulated in a commit object. OPTIONS ------- -include::diff-options.txt[] +include::diff-options.adoc[] <tree-ish>:: The id of a tree object. @@ -84,7 +84,7 @@ commits (but not trees). This flag causes 'git diff-tree --stdin' to also show the commit message before the differences. -include::pretty-options.txt[] +include::pretty-options.adoc[] --no-commit-id:: 'git diff-tree' outputs a line with the commit ID when @@ -122,9 +122,9 @@ include::pretty-options.txt[] if the diff itself is empty. -include::pretty-formats.txt[] +include::pretty-formats.adoc[] -include::diff-format.txt[] +include::diff-format.adoc[] GIT --- diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.adoc index e19f31e8b9..dec173a345 100644 --- a/Documentation/git-diff.txt +++ b/Documentation/git-diff.adoc @@ -123,7 +123,7 @@ do not mean a range as defined in the OPTIONS ------- :git-diff: 1 -include::diff-options.txt[] +include::diff-options.adoc[] `-1`:: `--base`:: @@ -154,7 +154,7 @@ section "3-Way Merge" for detailed information. names and get diff for all files under them). -include::diff-format.txt[] +include::diff-format.adoc[] EXAMPLES -------- @@ -232,10 +232,10 @@ $ git diff -R <2> CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] :git-diff: 1 -include::config/diff.txt[] +include::config/diff.adoc[] SEE ALSO -------- diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.adoc index a616f8b2e6..d596205eaf 100644 --- a/Documentation/git-difftool.txt +++ b/Documentation/git-difftool.adoc @@ -119,9 +119,9 @@ CONFIGURATION 'git difftool' falls back to 'git mergetool' config variables when the difftool equivalents have not been defined. -include::includes/cmd-config-section-rest.txt[] +include::includes/cmd-config-section-rest.adoc[] -include::config/difftool.txt[] +include::config/difftool.adoc[] SEE ALSO -------- diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.adoc index 752e4b9b01..413a527496 100644 --- a/Documentation/git-fast-export.txt +++ b/Documentation/git-fast-export.adoc @@ -27,17 +27,33 @@ OPTIONS Insert 'progress' statements every <n> objects, to be shown by 'git fast-import' during import. ---signed-tags=(verbatim|warn|warn-strip|strip|abort):: +--signed-tags=(verbatim|warn-verbatim|warn-strip|strip|abort):: Specify how to handle signed tags. Since any transformation - after the export can change the tag names (which can also happen - when excluding revisions) the signatures will not match. + after the export (or during the export, such as excluding + revisions) can change the hashes being signed, the signatures + may become invalid. + When asking to 'abort' (which is the default), this program will die when encountering a signed tag. With 'strip', the tags will silently be made unsigned, with 'warn-strip' they will be made unsigned but a warning will be displayed, with 'verbatim', they will be silently -exported and with 'warn', they will be exported, but you will see a -warning. +exported and with 'warn-verbatim' (or 'warn', a deprecated synonym), +they will be exported, but you will see a warning. 'verbatim' and +'warn-verbatim' should only be used if you know that no transformation +affecting tags or any commit in their history will be performed by you +or by fast-export or fast-import, or if you do not care that the +resulting tag will have an invalid signature. + +--signed-commits=(verbatim|warn-verbatim|warn-strip|strip|abort):: + Specify how to handle signed commits. Behaves exactly as + '--signed-tags', but for commits. Default is 'abort'. ++ +Earlier versions this command that did not have '--signed-commits' +behaved as if '--signed-commits=strip'. As an escape hatch for users +of tools that call 'git fast-export' but do not yet support +'--signed-commits', you may set the environment variable +'FAST_EXPORT_SIGNED_COMMITS_NOABORT=1' in order to change the default +from 'abort' to 'warn-strip'. --tag-of-filtered-object=(abort|drop|rewrite):: Specify how to handle tags whose tagged object is filtered out. diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.adoc index 3d435157a6..7b107f5e8e 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.adoc @@ -431,13 +431,22 @@ and control the current import process. More detailed discussion Create or update a branch with a new commit, recording one logical change to the project. +//// +Yes, it's intentional that the 'gpgsig' line doesn't have a trailing +`LF`; the definition of `data` has a byte-count prefix, so it +doesn't need an `LF` to act as a terminator (and `data` also already +includes an optional trailing `LF?` just in case you want to include +one). +//// + .... 'commit' SP <ref> LF mark? original-oid? ('author' (SP <name>)? SP LT <email> GT SP <when> LF)? 'committer' (SP <name>)? SP LT <email> GT SP <when> LF - ('encoding' SP <encoding>)? + ('gpgsig' SP <alg> LF data)? + ('encoding' SP <encoding> LF)? data ('from' SP <commit-ish> LF)? ('merge' SP <commit-ish> LF)* @@ -505,6 +514,15 @@ that was selected by the --date-format=<fmt> command-line option. See ``Date Formats'' above for the set of supported formats, and their syntax. +`gpgsig` +^^^^^^^^ + +The optional `gpgsig` command is used to include a PGP/GPG signature +that signs the commit data. + +Here <alg> specifies which hashing algorithm is used for this +signature, either `sha1` or `sha256`. + `encoding` ^^^^^^^^^^ The optional `encoding` command indicates the encoding of the commit @@ -1578,9 +1596,9 @@ compression. CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/fastimport.txt[] +include::config/fastimport.adoc[] SEE ALSO -------- diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.adoc index b5223576a7..b5223576a7 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.adoc diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.adoc index 50900a50da..16f5d9d69a 100644 --- a/Documentation/git-fetch.txt +++ b/Documentation/git-fetch.adoc @@ -44,15 +44,15 @@ may be used by scripts or other git commands, such as linkgit:git-pull[1]. OPTIONS ------- -include::fetch-options.txt[] +include::fetch-options.adoc[] -include::pull-fetch-param.txt[] +include::pull-fetch-param.adoc[] --stdin:: Read refspecs, one per line, from stdin in addition to those provided as arguments. The "tag <name>" format is not supported. -include::urls-remotes.txt[] +include::urls-remotes.adoc[] CONFIGURED REMOTE-TRACKING BRANCHES[[CRTB]] @@ -292,14 +292,14 @@ The first command fetches the `maint` branch from the repository at objects will eventually be removed by git's built-in housekeeping (see linkgit:git-gc[1]). -include::transfer-data-leaks.txt[] +include::transfer-data-leaks.adoc[] CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/fetch.txt[] +include::config/fetch.adoc[] BUGS ---- diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.adoc index 5a4f853785..5a4f853785 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.adoc diff --git a/Documentation/git-fmt-merge-msg.txt b/Documentation/git-fmt-merge-msg.adoc index 6f28812f38..0f3328956d 100644 --- a/Documentation/git-fmt-merge-msg.txt +++ b/Documentation/git-fmt-merge-msg.adoc @@ -55,7 +55,7 @@ OPTIONS CONFIGURATION ------------- -include::config/fmt-merge-msg.txt[] +include::config/fmt-merge-msg.adoc[] merge.summary:: Synonym to `merge.log`; this is deprecated and will be removed in diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.adoc index d3764401a2..5ef89fc0fe 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.adoc @@ -441,6 +441,7 @@ Ref: %(*refname) A simple example showing the use of shell eval on the output, demonstrating the use of --shell. List the prefixes of all heads: + ------------ #!/bin/sh @@ -455,6 +456,7 @@ done A bit more elaborate report on tags, demonstrating that the format may be an entire script: + ------------ #!/bin/sh @@ -538,7 +540,7 @@ will be reported. NOTES ----- -include::ref-reachability-filters.txt[] +include::ref-reachability-filters.adoc[] SEE ALSO -------- diff --git a/Documentation/git-for-each-repo.txt b/Documentation/git-for-each-repo.adoc index abe3527aac..abe3527aac 100644 --- a/Documentation/git-for-each-repo.txt +++ b/Documentation/git-for-each-repo.adoc diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.adoc index 5dc7bb4cfc..a8b53db9a6 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.adoc @@ -105,7 +105,7 @@ reference. OPTIONS ------- :git-format-patch: 1 -include::diff-options.txt[] +include::diff-options.adoc[] -<n>:: Prepare patches from the topmost <n> commits. diff --git a/Documentation/git-fsck-objects.txt b/Documentation/git-fsck-objects.adoc index eec4bdb600..eec4bdb600 100644 --- a/Documentation/git-fsck-objects.txt +++ b/Documentation/git-fsck-objects.adoc diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.adoc index 5b82e4605c..11203ba925 100644 --- a/Documentation/git-fsck.txt +++ b/Documentation/git-fsck.adoc @@ -12,7 +12,7 @@ SYNOPSIS 'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs] [--[no-]full] [--strict] [--verbose] [--lost-found] [--[no-]dangling] [--[no-]progress] [--connectivity-only] - [--[no-]name-objects] [<object>...] + [--[no-]name-objects] [--[no-]references] [<object>...] DESCRIPTION ----------- @@ -104,12 +104,17 @@ care about this output and want to speed it up further. progress status even if the standard error stream is not directed to a terminal. +--[no-]references:: + Control whether to check the references database consistency + via 'git refs verify'. See linkgit:git-refs[1] for details. + The default is to check the references database. + CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/fsck.txt[] +include::config/fsck.adoc[] DISCUSSION ---------- @@ -161,7 +166,7 @@ each error means, with their default severity. The severity of the error, other than those that are marked as "(FATAL)", can be tweaked by setting the corresponding `fsck.<msg-id>` configuration variable. -include::fsck-msgids.txt[] +include::fsck-msgids.adoc[] Environment Variables diff --git a/Documentation/git-fsmonitor--daemon.txt b/Documentation/git-fsmonitor--daemon.adoc index 8585d19f4d..8fe5241b08 100644 --- a/Documentation/git-fsmonitor--daemon.txt +++ b/Documentation/git-fsmonitor--daemon.adoc @@ -97,9 +97,9 @@ error that will cause the daemon and the currently running command to exit. CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/fsmonitor--daemon.txt[] +include::config/fsmonitor--daemon.adoc[] GIT --- diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.adoc index 370e22faae..526ce01463 100644 --- a/Documentation/git-gc.txt +++ b/Documentation/git-gc.adoc @@ -69,6 +69,13 @@ be performed as well. the `--max-cruft-size` option of linkgit:git-repack[1] for more. +--expire-to=<dir>:: + When packing unreachable objects into a cruft pack, write a cruft + pack containing pruned objects (if any) to the directory `<dir>`. + This option only has an effect when used together with `--cruft`. + See the `--expire-to` option of linkgit:git-repack[1] for + more information. + --prune=<date>:: Prune loose objects older than date (default is 2 weeks ago, overridable by the config variable `gc.pruneExpire`). @@ -122,9 +129,9 @@ users and their repositories. CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/gc.txt[] +include::config/gc.adoc[] NOTES ----- diff --git a/Documentation/git-get-tar-commit-id.txt b/Documentation/git-get-tar-commit-id.adoc index b537bb45b1..b537bb45b1 100644 --- a/Documentation/git-get-tar-commit-id.txt +++ b/Documentation/git-get-tar-commit-id.adoc diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.adoc index 1e6d7b65c8..a548585d4c 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.adoc @@ -351,9 +351,9 @@ experienced in this case, it might be desirable to use `--threads=1`. CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/grep.txt[] +include::config/grep.adoc[] GIT --- diff --git a/Documentation/git-gui.txt b/Documentation/git-gui.adoc index f5b02ef114..f5b02ef114 100644 --- a/Documentation/git-gui.txt +++ b/Documentation/git-gui.adoc diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.adoc index ef4719ae41..ef4719ae41 100644 --- a/Documentation/git-hash-object.txt +++ b/Documentation/git-hash-object.adoc diff --git a/Documentation/git-help.txt b/Documentation/git-help.adoc index f0bedc1f96..f0bedc1f96 100644 --- a/Documentation/git-help.txt +++ b/Documentation/git-help.adoc diff --git a/Documentation/git-hook.txt b/Documentation/git-hook.adoc index f6cc72d2ca..f6cc72d2ca 100644 --- a/Documentation/git-hook.txt +++ b/Documentation/git-hook.adoc diff --git a/Documentation/git-http-backend.txt b/Documentation/git-http-backend.adoc index f37ddaded8..1dea426852 100644 --- a/Documentation/git-http-backend.txt +++ b/Documentation/git-http-backend.adoc @@ -56,6 +56,10 @@ http.receivepack:: disabled by setting this item to `false`, or enabled for all users, including anonymous users, by setting it to `true`. +http.uploadarchive:: + This serves 'git archive' clients for remote archive over HTTP/HTTPS + protocols. It is disabled by default. It only works in protocol v2. + URL TRANSLATION --------------- To determine the location of the repository on disk, 'git http-backend' diff --git a/Documentation/git-http-fetch.txt b/Documentation/git-http-fetch.adoc index 4ec7c68d3b..4ec7c68d3b 100644 --- a/Documentation/git-http-fetch.txt +++ b/Documentation/git-http-fetch.adoc diff --git a/Documentation/git-http-push.txt b/Documentation/git-http-push.adoc index ce0d808212..ce0d808212 100644 --- a/Documentation/git-http-push.txt +++ b/Documentation/git-http-push.adoc diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.adoc index c8a89d7243..26ccf4e433 100644 --- a/Documentation/git-imap-send.txt +++ b/Documentation/git-imap-send.adoc @@ -54,9 +54,9 @@ CONFIGURATION To use the tool, `imap.folder` and either `imap.tunnel` or `imap.host` must be set to appropriate values. -include::includes/cmd-config-section-rest.txt[] +include::includes/cmd-config-section-rest.adoc[] -include::config/imap.txt[] +include::config/imap.adoc[] EXAMPLES -------- diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.adoc index 58dd5b5f0e..270056cf63 100644 --- a/Documentation/git-index-pack.txt +++ b/Documentation/git-index-pack.adoc @@ -130,7 +130,7 @@ information on the possible values of `<msg-id>` and `<severity>`. + This option cannot be used with --stdin. + -include::object-format-disclaimer.txt[] +include::object-format-disclaimer.adoc[] --promisor[=<message>]:: Before committing the pack-index, create a .promisor file for this diff --git a/Documentation/git-init-db.txt b/Documentation/git-init-db.adoc index 18bf1a3c8c..18bf1a3c8c 100644 --- a/Documentation/git-init-db.txt +++ b/Documentation/git-init-db.adoc diff --git a/Documentation/git-init.txt b/Documentation/git-init.adoc index 315f7f7530..a0dffba665 100644 --- a/Documentation/git-init.txt +++ b/Documentation/git-init.adoc @@ -55,12 +55,12 @@ current working directory. Specify the given object _<format>_ (hash algorithm) for the repository. The valid values are `sha1` and (if enabled) `sha256`. `sha1` is the default. + -include::object-format-disclaimer.txt[] +include::object-format-disclaimer.adoc[] `--ref-format=<format>`:: Specify the given ref storage _<format>_ for the repository. The valid values are: + -include::ref-storage-format.txt[] +include::ref-storage-format.adoc[] `--template=<template-directory>`:: Specify the directory from which templates will be used. (See the "TEMPLATE @@ -178,11 +178,11 @@ $ git commit <3> CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] :git-init: -include::config/init.txt[] +include::config/init.adoc[] GIT --- diff --git a/Documentation/git-instaweb.txt b/Documentation/git-instaweb.adoc index a54fe4401b..a54fe4401b 100644 --- a/Documentation/git-instaweb.txt +++ b/Documentation/git-instaweb.adoc diff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.adoc index d9dfb75fef..82c8780d93 100644 --- a/Documentation/git-interpret-trailers.txt +++ b/Documentation/git-interpret-trailers.adoc @@ -186,142 +186,9 @@ OPTIONS CONFIGURATION VARIABLES ----------------------- -trailer.separators:: - This option tells which characters are recognized as trailer - separators. By default only ':' is recognized as a trailer - separator, except that '=' is always accepted on the command - line for compatibility with other git commands. -+ -The first character given by this option will be the default character -used when another separator is not specified in the config for this -trailer. -+ -For example, if the value for this option is "%=$", then only lines -using the format '<key><sep><value>' with <sep> containing '%', '=' -or '$' and then spaces will be considered trailers. And '%' will be -the default separator used, so by default trailers will appear like: -'<key>% <value>' (one percent sign and one space will appear between -the key and the value). - -trailer.where:: - This option tells where a new trailer will be added. -+ -This can be `end`, which is the default, `start`, `after` or `before`. -+ -If it is `end`, then each new trailer will appear at the end of the -existing trailers. -+ -If it is `start`, then each new trailer will appear at the start, -instead of the end, of the existing trailers. -+ -If it is `after`, then each new trailer will appear just after the -last trailer with the same <key>. -+ -If it is `before`, then each new trailer will appear just before the -first trailer with the same <key>. +include::includes/cmd-config-section-all.adoc[] -trailer.ifexists:: - This option makes it possible to choose what action will be - performed when there is already at least one trailer with the - same <key> in the input. -+ -The valid values for this option are: `addIfDifferentNeighbor` (this -is the default), `addIfDifferent`, `add`, `replace` or `doNothing`. -+ -With `addIfDifferentNeighbor`, a new trailer will be added only if no -trailer with the same (<key>, <value>) pair is above or below the line -where the new trailer will be added. -+ -With `addIfDifferent`, a new trailer will be added only if no trailer -with the same (<key>, <value>) pair is already in the input. -+ -With `add`, a new trailer will be added, even if some trailers with -the same (<key>, <value>) pair are already in the input. -+ -With `replace`, an existing trailer with the same <key> will be -deleted and the new trailer will be added. The deleted trailer will be -the closest one (with the same <key>) to the place where the new one -will be added. -+ -With `doNothing`, nothing will be done; that is no new trailer will be -added if there is already one with the same <key> in the input. - -trailer.ifmissing:: - This option makes it possible to choose what action will be - performed when there is not yet any trailer with the same - <key> in the input. -+ -The valid values for this option are: `add` (this is the default) and -`doNothing`. -+ -With `add`, a new trailer will be added. -+ -With `doNothing`, nothing will be done. - -trailer.<keyAlias>.key:: - Defines a <keyAlias> for the <key>. The <keyAlias> must be a - prefix (case does not matter) of the <key>. For example, in `git - config trailer.ack.key "Acked-by"` the "Acked-by" is the <key> and - the "ack" is the <keyAlias>. This configuration allows the shorter - `--trailer "ack:..."` invocation on the command line using the "ack" - <keyAlias> instead of the longer `--trailer "Acked-by:..."`. -+ -At the end of the <key>, a separator can appear and then some -space characters. By default the only valid separator is ':', -but this can be changed using the `trailer.separators` config -variable. -+ -If there is a separator in the key, then it overrides the default -separator when adding the trailer. - -trailer.<keyAlias>.where:: - This option takes the same values as the 'trailer.where' - configuration variable and it overrides what is specified by - that option for trailers with the specified <keyAlias>. - -trailer.<keyAlias>.ifexists:: - This option takes the same values as the 'trailer.ifexists' - configuration variable and it overrides what is specified by - that option for trailers with the specified <keyAlias>. - -trailer.<keyAlias>.ifmissing:: - This option takes the same values as the 'trailer.ifmissing' - configuration variable and it overrides what is specified by - that option for trailers with the specified <keyAlias>. - -trailer.<keyAlias>.command:: - Deprecated in favor of 'trailer.<keyAlias>.cmd'. - This option behaves in the same way as 'trailer.<keyAlias>.cmd', except - that it doesn't pass anything as argument to the specified command. - Instead the first occurrence of substring $ARG is replaced by the - <value> that would be passed as argument. -+ -Note that $ARG in the user's command is -only replaced once and that the original way of replacing $ARG is not safe. -+ -When both 'trailer.<keyAlias>.cmd' and 'trailer.<keyAlias>.command' are given -for the same <keyAlias>, 'trailer.<keyAlias>.cmd' is used and -'trailer.<keyAlias>.command' is ignored. - -trailer.<keyAlias>.cmd:: - This option can be used to specify a shell command that will be called - once to automatically add a trailer with the specified <keyAlias>, and then - called each time a '--trailer <keyAlias>=<value>' argument is specified to - modify the <value> of the trailer that this option would produce. -+ -When the specified command is first called to add a trailer -with the specified <keyAlias>, the behavior is as if a special -'--trailer <keyAlias>=<value>' argument was added at the beginning -of the "git interpret-trailers" command, where <value> -is taken to be the standard output of the command with any -leading and trailing whitespace trimmed off. -+ -If some '--trailer <keyAlias>=<value>' arguments are also passed -on the command line, the command is called again once for each -of these arguments with the same <keyAlias>. And the <value> part -of these arguments, if any, will be passed to the command as its -first argument. This way the command can produce a <value> computed -from the <value> passed in the '--trailer <keyAlias>=<value>' argument. +include::config/trailer.adoc[] EXAMPLES -------- diff --git a/Documentation/git-log.txt b/Documentation/git-log.adoc index 579682172f..ae8a7e2d63 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.adoc @@ -16,7 +16,7 @@ DESCRIPTION Shows the commit logs. :git-log: 1 -include::rev-list-description.txt[] +include::rev-list-description.adoc[] The command takes options applicable to the linkgit:git-rev-list[1] command to control what is shown and how, and options applicable to @@ -89,7 +89,7 @@ produced by `--stat`, etc. Intended to speed up tools that read log messages from `git log` output by allowing them to allocate space in advance. -include::line-range-options.txt[] +include::line-range-options.adoc[] <revision-range>:: Show only commits in the specified revision range. When no @@ -109,9 +109,9 @@ include::line-range-options.txt[] Paths may need to be prefixed with `--` to separate them from options or the revision range, when confusion arises. -include::rev-list-options.txt[] +include::rev-list-options.adoc[] -include::pretty-formats.txt[] +include::pretty-formats.adoc[] DIFF FORMATTING --------------- @@ -128,9 +128,9 @@ the default format for merge commits. :git-log: 1 :diff-merges-default: `off` -include::diff-options.txt[] +include::diff-options.adoc[] -include::diff-generate-patch.txt[] +include::diff-generate-patch.adoc[] EXAMPLES -------- @@ -192,7 +192,7 @@ EXAMPLES DISCUSSION ---------- -include::i18n.txt[] +include::i18n.adoc[] CONFIGURATION ------------- @@ -209,11 +209,11 @@ i18n.logOutputEncoding:: Defaults to the value of `i18n.commitEncoding` if set, and UTF-8 otherwise. -include::includes/cmd-config-section-rest.txt[] +include::includes/cmd-config-section-rest.adoc[] -include::config/log.txt[] +include::config/log.adoc[] -include::config/notes.txt[] +include::config/notes.adoc[] GIT --- diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.adoc index 58c529afbe..58c529afbe 100644 --- a/Documentation/git-ls-files.txt +++ b/Documentation/git-ls-files.adoc diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.adoc index d71c4ab3e2..d71c4ab3e2 100644 --- a/Documentation/git-ls-remote.txt +++ b/Documentation/git-ls-remote.adoc diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.adoc index 6572095d8d..6572095d8d 100644 --- a/Documentation/git-ls-tree.txt +++ b/Documentation/git-ls-tree.adoc diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.adoc index 28060283c7..3b24c9abd9 100644 --- a/Documentation/git-mailinfo.txt +++ b/Documentation/git-mailinfo.adoc @@ -118,9 +118,9 @@ If no such configuration option has been set, `warn` will be used. CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/mailinfo.txt[] +include::config/mailinfo.adoc[] GIT --- diff --git a/Documentation/git-mailsplit.txt b/Documentation/git-mailsplit.adoc index 3f0a6662c8..3f0a6662c8 100644 --- a/Documentation/git-mailsplit.txt +++ b/Documentation/git-mailsplit.adoc diff --git a/Documentation/git-maintenance.txt b/Documentation/git-maintenance.adoc index 6e6651309d..0450d74aff 100644 --- a/Documentation/git-maintenance.txt +++ b/Documentation/git-maintenance.adoc @@ -409,9 +409,9 @@ custom tasks. CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/maintenance.txt[] +include::config/maintenance.adoc[] GIT diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.adoc index 5ab957cfbc..5ab957cfbc 100644 --- a/Documentation/git-merge-base.txt +++ b/Documentation/git-merge-base.adoc diff --git a/Documentation/git-merge-file.txt b/Documentation/git-merge-file.adoc index 71915a00fa..71915a00fa 100644 --- a/Documentation/git-merge-file.txt +++ b/Documentation/git-merge-file.adoc diff --git a/Documentation/git-merge-index.txt b/Documentation/git-merge-index.adoc index eea56b3154..eea56b3154 100644 --- a/Documentation/git-merge-index.txt +++ b/Documentation/git-merge-index.adoc diff --git a/Documentation/git-merge-one-file.txt b/Documentation/git-merge-one-file.adoc index 04e803d5d3..04e803d5d3 100644 --- a/Documentation/git-merge-one-file.txt +++ b/Documentation/git-merge-one-file.adoc diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.adoc index 0b6a8a19b1..cf0578f9b5 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.adoc @@ -40,11 +40,17 @@ After the merge completes, a new toplevel tree object is created. See OPTIONS ------- +--stdin:: + Read the commits to merge from the standard input rather than + the command-line. See <<INPUT,INPUT FORMAT>> below for more + information. Implies `-z`. + -z:: Do not quote filenames in the <Conflicted file info> section, and end each filename with a NUL character rather than newline. Also begin the messages section with a NUL character - instead of a newline. See <<OUTPUT>> below for more information. + instead of a newline. See <<OUTPUT,OUTPUT>> below for more + information. --name-only:: In the Conflicted file info section, instead of writing a list @@ -116,8 +122,6 @@ This is an integer status followed by a NUL character. The integer status is: 0: merge had conflicts 1: merge was clean - <0: something prevented the merge from running (e.g. access to repository - objects denied by filesystem) [[OIDTLT]] OID of toplevel tree @@ -235,6 +239,7 @@ with linkgit:git-merge[1]: * any messages that would have been printed to stdout (the <<IM,Informational messages>>) +[[INPUT]] INPUT FORMAT ------------ 'git merge-tree --stdin' input format is fully text based. Each line diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.adoc index 1ab69f61f5..64281d6d44 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.adoc @@ -65,7 +65,7 @@ OPTIONS ------- :git-merge: 1 -include::merge-options.txt[] +include::merge-options.adoc[] -m <msg>:: Set the commit message to be used for the merge commit (in @@ -91,7 +91,7 @@ invocations. The automated message can include the branch description. If `--log` is specified, a shortlog of the commits being merged will be appended to the specified message. -include::rerere-options.txt[] +include::rerere-options.adoc[] --overwrite-ignore:: --no-overwrite-ignore:: @@ -385,7 +385,7 @@ changes into a merge commit. Small fixups like bumping release/version name would be acceptable. -include::merge-strategies.txt[] +include::merge-strategies.adoc[] CONFIGURATION ------------- @@ -395,9 +395,9 @@ branch.<name>.mergeOptions:: supported options are the same as those of `git merge`, but option values containing whitespace characters are currently not supported. -include::includes/cmd-config-section-rest.txt[] +include::includes/cmd-config-section-rest.adoc[] -include::config/merge.txt[] +include::config/merge.adoc[] SEE ALSO -------- diff --git a/Documentation/git-mergetool--lib.txt b/Documentation/git-mergetool--lib.adoc index 0726b560d4..0726b560d4 100644 --- a/Documentation/git-mergetool--lib.txt +++ b/Documentation/git-mergetool--lib.adoc diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.adoc index b9e20c5dcd..046c3258f0 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.adoc @@ -104,9 +104,9 @@ CONFIGURATION ------------- :git-mergetool: 1 -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/mergetool.txt[] +include::config/mergetool.adoc[] TEMPORARY FILES --------------- @@ -123,7 +123,7 @@ BACKEND SPECIFIC HINTS vimdiff ~~~~~~~ -include::mergetools/vimdiff.txt[] +include::mergetools/vimdiff.adoc[] GIT --- diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.adoc index 006d759962..006d759962 100644 --- a/Documentation/git-mktag.txt +++ b/Documentation/git-mktag.adoc diff --git a/Documentation/git-mktree.txt b/Documentation/git-mktree.adoc index 383f09dd33..383f09dd33 100644 --- a/Documentation/git-mktree.txt +++ b/Documentation/git-mktree.adoc diff --git a/Documentation/git-multi-pack-index.txt b/Documentation/git-multi-pack-index.adoc index 631d5c7d15..631d5c7d15 100644 --- a/Documentation/git-multi-pack-index.txt +++ b/Documentation/git-multi-pack-index.adoc diff --git a/Documentation/git-mv.txt b/Documentation/git-mv.adoc index dc1bf61534..dc1bf61534 100644 --- a/Documentation/git-mv.txt +++ b/Documentation/git-mv.adoc diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.adoc index d4f1c4d594..d4f1c4d594 100644 --- a/Documentation/git-name-rev.txt +++ b/Documentation/git-name-rev.adoc diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.adoc index 84022f99d7..bcfe3dacd3 100644 --- a/Documentation/git-notes.txt +++ b/Documentation/git-notes.adoc @@ -7,19 +7,19 @@ git-notes - Add or inspect object notes SYNOPSIS -------- -[verse] -'git notes' [list [<object>]] -'git notes' add [-f] [--allow-empty] [--[no-]separator | --separator=<paragraph-break>] [--[no-]stripspace] [-F <file> | -m <msg> | (-c | -C) <object>] [-e] [<object>] -'git notes' copy [-f] ( --stdin | <from-object> [<to-object>] ) -'git notes' append [--allow-empty] [--[no-]separator | --separator=<paragraph-break>] [--[no-]stripspace] [-F <file> | -m <msg> | (-c | -C) <object>] [-e] [<object>] -'git notes' edit [--allow-empty] [<object>] [--[no-]stripspace] -'git notes' show [<object>] -'git notes' merge [-v | -q] [-s <strategy> ] <notes-ref> -'git notes' merge --commit [-v | -q] -'git notes' merge --abort [-v | -q] -'git notes' remove [--ignore-missing] [--stdin] [<object>...] -'git notes' prune [-n] [-v] -'git notes' get-ref +[synopsis] +git notes [list [<object>]] +git notes add [-f] [--allow-empty] [--[no-]separator | --separator=<paragraph-break>] [--[no-]stripspace] [-F <file> | -m <msg> | (-c | -C) <object>] [-e] [<object>] +git notes copy [-f] ( --stdin | <from-object> [<to-object>] ) +git notes append [--allow-empty] [--[no-]separator | --separator=<paragraph-break>] [--[no-]stripspace] [-F <file> | -m <msg> | (-c | -C) <object>] [-e] [<object>] +git notes edit [--allow-empty] [<object>] [--[no-]stripspace] +git notes show [<object>] +git notes merge [-v | -q] [-s <strategy> ] <notes-ref> +git notes merge --commit [-v | -q] +git notes merge --abort [-v | -q] +git notes remove [--ignore-missing] [--stdin] [<object>...] +git notes prune [-n] [-v] +git notes get-ref DESCRIPTION @@ -33,34 +33,34 @@ ENVIRONMENT sections below. If this ref does not exist, it will be quietly created when it is first needed to store a note. A typical use of notes is to supplement a commit message without -changing the commit itself. Notes can be shown by 'git log' along with +changing the commit itself. Notes can be shown by `git log` along with the original commit message. To distinguish these notes from the message stored in the commit object, the notes are indented like the -message, after an unindented line saying "Notes (<refname>):" (or +message, after an unindented line saying "Notes (_<refname>_):" (or "Notes:" for `refs/notes/commits`). Notes can also be added to patches prepared with `git format-patch` by using the `--notes` option. Such notes are added as a patch commentary after a three dash separator line. -To change which notes are shown by 'git log', see the -"notes.displayRef" discussion in <<CONFIGURATION>>. +To change which notes are shown by `git log`, see the +`notes.displayRef` discussion in <<CONFIGURATION,CONFIGURATION>>. -See the "notes.rewrite.<command>" configuration for a way to carry +See the `notes.rewrite.<command>` configuration for a way to carry notes across commands that rewrite commits. SUBCOMMANDS ----------- -list:: +`list`:: List the notes object for a given object. If no object is given, show a list of all note objects and the objects they - annotate (in the format "<note-object> <annotated-object>"). + annotate (in the format "`<note-object> <annotated-object>`"). This is the default subcommand if no subcommand is given. -add:: - Add notes for a given object (defaults to HEAD). Abort if the +`add`:: + Add notes for a given object (defaults to `HEAD`). Abort if the object already has notes (use `-f` to overwrite existing notes). However, if you're using `add` interactively (using an editor to supply the notes contents), then - instead of aborting - @@ -71,10 +71,10 @@ add:: fine-tune the message(s) supplied from `-m` and `-F` options interactively (using an editor) before adding the note. -copy:: +`copy`:: Copy the notes for the first object onto the second object (defaults to - HEAD). Abort if the second object already has notes, or if the first - object has none (use -f to overwrite existing notes to the + `HEAD`). Abort if the second object already has notes, or if the first + object has none (use `-f` to overwrite existing notes to the second object). This subcommand is equivalent to: `git notes add [-f] -C $(git notes list <from-object>) <to-object>` + @@ -84,27 +84,27 @@ In `--stdin` mode, take lines in the format <from-object> SP <to-object> [ SP <rest> ] LF ---------- + -on standard input, and copy the notes from each <from-object> to its -corresponding <to-object>. (The optional `<rest>` is ignored so that +on standard input, and copy the notes from each _<from-object>_ to its +corresponding _<to-object>_. (The optional _<rest>_ is ignored so that the command can read the input given to the `post-rewrite` hook.) -append:: +`append`:: Append new message(s) given by `-m` or `-F` options to an existing note, or add them as a new note if one does not - exist, for the object (defaults to HEAD). When appending to + exist, for the object (defaults to `HEAD`). When appending to an existing note, a blank line is added before each new message as an inter-paragraph separator. The separator can be customized with the `--separator` option. Edit the notes to be appended given by `-m` and `-F` options with `-e` interactively (using an editor) before appending the note. -edit:: - Edit the notes for a given object (defaults to HEAD). +`edit`:: + Edit the notes for a given object (defaults to `HEAD`). -show:: - Show the notes for a given object (defaults to HEAD). +`show`:: + Show the notes for a given object (defaults to `HEAD`). -merge:: +`merge`:: Merge the given notes ref into the current notes ref. This will try to merge the changes made by the given notes ref (called "remote") since the merge-base (if @@ -112,35 +112,35 @@ merge:: + If conflicts arise and a strategy for automatically resolving conflicting notes (see the "NOTES MERGE STRATEGIES" section) is not given, -the "manual" resolver is used. This resolver checks out the +the `manual` resolver is used. This resolver checks out the conflicting notes in a special worktree (`.git/NOTES_MERGE_WORKTREE`), and instructs the user to manually resolve the conflicts there. When done, the user can either finalize the merge with -'git notes merge --commit', or abort the merge with -'git notes merge --abort'. +`git notes merge --commit`, or abort the merge with +`git notes merge --abort`. -remove:: - Remove the notes for given objects (defaults to HEAD). When +`remove`:: + Remove the notes for given objects (defaults to `HEAD`). When giving zero or one object from the command line, this is equivalent to specifying an empty note message to the `edit` subcommand. -prune:: +`prune`:: Remove all notes for non-existing/unreachable objects. -get-ref:: +`get-ref`:: Print the current notes ref. This provides an easy way to retrieve the current notes ref (e.g. from scripts). OPTIONS ------- --f:: ---force:: +`-f`:: +`--force`:: When adding notes to an object that already has notes, overwrite the existing notes (instead of aborting). --m <msg>:: ---message=<msg>:: +`-m <msg>`:: +`--message=<msg>`:: Use the given note message (instead of prompting). If multiple `-m` options are given, their values are concatenated as separate paragraphs. @@ -148,95 +148,96 @@ OPTIONS single line between paragraphs will be stripped out. If you wish to keep them verbatim, use `--no-stripspace`. --F <file>:: ---file=<file>:: - Take the note message from the given file. Use '-' to +`-F <file>`:: +`--file=<file>`:: + Take the note message from the given file. Use `-` to read the note message from the standard input. Lines starting with `#` and empty lines other than a single line between paragraphs will be stripped out. If you wish to keep them verbatim, use `--no-stripspace`. --C <object>:: ---reuse-message=<object>:: +`-C <object>`:: +`--reuse-message=<object>`:: Take the given blob object (for example, another note) as the note message. (Use `git notes copy <object>` instead to copy notes between objects.). By default, message will be copied verbatim, but if you wish to strip out the lines starting with `#` and empty lines other than a single line - between paragraphs, use with`--stripspace` option. + between paragraphs, use with `--stripspace` option. --c <object>:: ---reedit-message=<object>:: - Like '-C', but with `-c` the editor is invoked, so that +`-c <object>`:: +`--reedit-message=<object>`:: + Like `-C`, but with `-c` the editor is invoked, so that the user can further edit the note message. ---allow-empty:: +`--allow-empty`:: Allow an empty note object to be stored. The default behavior is to automatically remove empty notes. ---[no-]separator, --separator=<paragraph-break>:: +`--[no-]separator`:: +`--separator=<paragraph-break>`:: Specify a string used as a custom inter-paragraph separator (a newline is added at the end as needed). If `--no-separator`, no separators will be added between paragraphs. Defaults to a blank line. ---[no-]stripspace:: +`--[no-]stripspace`:: Strip leading and trailing whitespace from the note message. Also strip out empty lines other than a single line between paragraphs. Lines starting with `#` will be stripped out in non-editor cases like `-m`, `-F` and `-C`, but not in editor case like `git notes edit`, `-c`, etc. ---ref <ref>:: - Manipulate the notes tree in <ref>. This overrides - `GIT_NOTES_REF` and the "core.notesRef" configuration. The ref +`--ref <ref>`:: + Manipulate the notes tree in _<ref>_. This overrides + `GIT_NOTES_REF` and the `core.notesRef` configuration. The ref specifies the full refname when it begins with `refs/notes/`; when it begins with `notes/`, `refs/` and otherwise `refs/notes/` is prefixed to form a full name of the ref. ---ignore-missing:: +`--ignore-missing`:: Do not consider it an error to request removing notes from an object that does not have notes attached to it. ---stdin:: +`--stdin`:: Also read the object names to remove notes from the standard input (there is no reason you cannot combine this with object names from the command line). --n:: ---dry-run:: +`-n`:: +`--dry-run`:: Do not remove anything; just report the object names whose notes would be removed. --s <strategy>:: ---strategy=<strategy>:: +`-s <strategy>`:: +`--strategy=<strategy>`:: When merging notes, resolve notes conflicts using the given - strategy. The following strategies are recognized: "manual" - (default), "ours", "theirs", "union" and "cat_sort_uniq". - This option overrides the "notes.mergeStrategy" configuration setting. + strategy. The following strategies are recognized: `manual` + (default), `ours`, `theirs`, `union` and `cat_sort_uniq`. + This option overrides the `notes.mergeStrategy` configuration setting. See the "NOTES MERGE STRATEGIES" section below for more information on each notes merge strategy. ---commit:: - Finalize an in-progress 'git notes merge'. Use this option - when you have resolved the conflicts that 'git notes merge' - stored in .git/NOTES_MERGE_WORKTREE. This amends the partial - merge commit created by 'git notes merge' (stored in - .git/NOTES_MERGE_PARTIAL) by adding the notes in - .git/NOTES_MERGE_WORKTREE. The notes ref stored in the - .git/NOTES_MERGE_REF symref is updated to the resulting commit. - ---abort:: - Abort/reset an in-progress 'git notes merge', i.e. a notes merge +`--commit`:: + Finalize an in-progress `git notes merge`. Use this option + when you have resolved the conflicts that `git notes merge` + stored in `.git/NOTES_MERGE_WORKTREE`. This amends the partial + merge commit created by `git notes merge` (stored in + `.git/NOTES_MERGE_PARTIAL`) by adding the notes in + `.git/NOTES_MERGE_WORKTREE`. The notes ref stored in the + `.git/NOTES_MERGE_REF` symref is updated to the resulting commit. + +`--abort`:: + Abort/reset an in-progress `git notes merge`, i.e. a notes merge with conflicts. This simply removes all files related to the notes merge. --q:: ---quiet:: +`-q`:: +`--quiet`:: When merging notes, operate quietly. --v:: ---verbose:: +`-v`:: +`--verbose`:: When merging notes, be more verbose. When pruning notes, report all object names whose notes are removed. @@ -270,28 +271,28 @@ object, in which case the history of the notes can be read with NOTES MERGE STRATEGIES ---------------------- -The default notes merge strategy is "manual", which checks out +The default notes merge strategy is `manual`, which checks out conflicting notes in a special work tree for resolving notes conflicts (`.git/NOTES_MERGE_WORKTREE`), and instructs the user to resolve the conflicts in that work tree. When done, the user can either finalize the merge with -'git notes merge --commit', or abort the merge with -'git notes merge --abort'. +`git notes merge --commit`, or abort the merge with +`git notes merge --abort`. Users may select an automated merge strategy from among the following using -either -s/--strategy option or configuring notes.mergeStrategy accordingly: +either `-s`/`--strategy` option or configuring `notes.mergeStrategy` accordingly: -"ours" automatically resolves conflicting notes in favor of the local +`ours` automatically resolves conflicting notes in favor of the local version (i.e. the current notes ref). -"theirs" automatically resolves notes conflicts in favor of the remote +`theirs` automatically resolves notes conflicts in favor of the remote version (i.e. the given notes ref being merged into the current notes ref). -"union" automatically resolves notes conflicts by concatenating the +`union` automatically resolves notes conflicts by concatenating the local and remote versions. -"cat_sort_uniq" is similar to "union", but in addition to concatenating +`cat_sort_uniq` is similar to `union`, but in addition to concatenating the local and remote versions, this strategy also sorts the resulting lines, and removes duplicate lines from the result. This is equivalent to applying the "cat | sort | uniq" shell pipeline to the local and @@ -320,7 +321,7 @@ Notes: In principle, a note is a regular Git blob, and any kind of (non-)format is accepted. You can binary-safely create notes from -arbitrary files using 'git hash-object': +arbitrary files using `git hash-object`: ------------ $ cc *.c @@ -331,7 +332,7 @@ $ git notes --ref=built add --allow-empty -C "$blob" HEAD (You cannot simply use `git notes --ref=built add -F a.out HEAD` because that is not binary-safe.) Of course, it doesn't make much sense to display non-text-format notes -with 'git log', so if you use such notes, you'll probably need to write +with `git log`, so if you use such notes, you'll probably need to write some special-purpose tools to do something useful with them. @@ -339,15 +340,15 @@ some special-purpose tools to do something useful with them. CONFIGURATION ------------- -core.notesRef:: +`core.notesRef`:: Notes ref to read and manipulate instead of `refs/notes/commits`. Must be an unabbreviated ref name. This setting can be overridden through the environment and command line. -include::includes/cmd-config-section-rest.txt[] +include::includes/cmd-config-section-rest.adoc[] -include::config/notes.txt[] +include::config/notes.adoc[] ENVIRONMENT diff --git a/Documentation/git-p4.txt b/Documentation/git-p4.adoc index de5ee6748e..f97b786bf9 100644 --- a/Documentation/git-p4.txt +++ b/Documentation/git-p4.adoc @@ -80,6 +80,7 @@ This: To reproduce the entire p4 history in Git, use the '@all' modifier on the depot path: + ------------ $ git p4 clone //depot/path/project@all ------------ @@ -89,19 +90,23 @@ Sync ~~~~ As development continues in the p4 repository, those changes can be included in the Git repository using: + ------------ $ git p4 sync ------------ + This command finds new changes in p4 and imports them as Git commits. P4 repositories can be added to an existing Git repository using 'git p4 sync' too: + ------------ $ mkdir repo-git $ cd repo-git $ git init $ git p4 sync //path/in/your/perforce/depot ------------ + This imports the specified depot into 'refs/remotes/p4/master' in an existing Git repository. The `--branch` option can be used to specify a different branch to @@ -125,6 +130,7 @@ and merge them with local uncommitted changes. Often, the p4 repository is the ultimate location for all code, thus a rebase workflow makes sense. This command does 'git p4 sync' followed by 'git rebase' to move local commits on top of updated p4 changes. + ------------ $ git p4 rebase ------------ @@ -140,16 +146,19 @@ will be created and populated if it does not already exist. To submit all changes that are in the current Git branch but not in the 'p4/master' branch, use: + ------------ $ git p4 submit ------------ To specify a branch other than the current one, use: + ------------ $ git p4 submit topicbranch ------------ To specify a single commit or a range of commits, use: + ------------ $ git p4 submit --commit <sha1> $ git p4 submit --commit <sha1..sha1> @@ -510,20 +519,24 @@ when cloning or syncing to have 'git p4' automatically find subdirectories in p4, and to generate these as branches in Git. For example, if the P4 repository structure is: + ---- //depot/main/... //depot/branch1/... ---- And "p4 branch -o branch1" shows a View line that looks like: + ---- //depot/main/... //depot/branch1/... ---- Then this 'git p4 clone' command: + ---- git p4 clone --detect-branches //depot@all ---- + produces a separate branch in 'refs/remotes/p4/' for //depot/main, called 'master', and one for //depot/branch1 called 'depot/branch1'. @@ -536,6 +549,7 @@ simple p4 branch specification, where the "source" and "destination" are the path elements in the p4 repository. The example above relied on the presence of the p4 branch. Without p4 branches, the same result will occur with: + ---- git init depot cd depot diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.adoc index e32404c6aa..7f69ae4855 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.adoc @@ -15,7 +15,8 @@ SYNOPSIS [--revs [--unpacked | --all]] [--keep-pack=<pack-name>] [--cruft] [--cruft-expiration=<time>] [--stdout [--filter=<filter-spec>] | <base-name>] - [--shallow] [--keep-true-parents] [--[no-]sparse] < <object-list> + [--shallow] [--keep-true-parents] [--[no-]sparse] + [--name-hash-version=<n>] < <object-list> DESCRIPTION @@ -345,6 +346,35 @@ raise an error. Restrict delta matches based on "islands". See DELTA ISLANDS below. +--name-hash-version=<n>:: + While performing delta compression, Git groups objects that may be + similar based on heuristics using the path to that object. While + grouping objects by an exact path match is good for paths with + many versions, there are benefits for finding delta pairs across + different full paths. Git collects objects by type and then by a + "name hash" of the path and then by size, hoping to group objects + that will compress well together. ++ +The default name hash version is `1`, which prioritizes hash locality by +considering the final bytes of the path as providing the maximum magnitude +to the hash function. This version excels at distinguishing short paths +and finding renames across directories. However, the hash function depends +primarily on the final 16 bytes of the path. If there are many paths in +the repo that have the same final 16 bytes and differ only by parent +directory, then this name-hash may lead to too many collisions and cause +poor results. At the moment, this version is required when writing +reachability bitmap files with `--write-bitmap-index`. ++ +The name hash version `2` has similar locality features as version `1`, +except it considers each path component separately and overlays the hashes +with a shift. This still prioritizes the final bytes of the path, but also +"salts" the lower bits of the hash using the parent directory names. This +method allows for some of the locality benefits of version `1` while +breaking most of the collisions from a similarly-named file appearing in +many different directories. At the moment, this version is not allowed +when writing reachability bitmap files with `--write-bitmap-index` and it +will be automatically changed to version `1`. + DELTA ISLANDS ------------- diff --git a/Documentation/git-pack-redundant.txt b/Documentation/git-pack-redundant.adoc index 13c3eb5ec9..13c3eb5ec9 100644 --- a/Documentation/git-pack-redundant.txt +++ b/Documentation/git-pack-redundant.adoc diff --git a/Documentation/git-pack-refs.txt b/Documentation/git-pack-refs.adoc index 2dcabaf74c..2dcabaf74c 100644 --- a/Documentation/git-pack-refs.txt +++ b/Documentation/git-pack-refs.adoc diff --git a/Documentation/git-patch-id.txt b/Documentation/git-patch-id.adoc index 1d15fa45d5..1d15fa45d5 100644 --- a/Documentation/git-patch-id.txt +++ b/Documentation/git-patch-id.adoc diff --git a/Documentation/git-prune-packed.txt b/Documentation/git-prune-packed.adoc index db742dcfee..db742dcfee 100644 --- a/Documentation/git-prune-packed.txt +++ b/Documentation/git-prune-packed.adoc diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.adoc index 9a45571b90..9a45571b90 100644 --- a/Documentation/git-prune.txt +++ b/Documentation/git-prune.adoc diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.adoc index b2ae496e48..3f4ecc4730 100644 --- a/Documentation/git-pull.txt +++ b/Documentation/git-pull.adoc @@ -102,7 +102,7 @@ Options related to merging :git-pull: 1 -include::merge-options.txt[] +include::merge-options.adoc[] -r:: --rebase[=(false|true|merges|interactive)]:: @@ -136,13 +136,13 @@ unless you have read linkgit:git-rebase[1] carefully. Options related to fetching ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -include::fetch-options.txt[] +include::fetch-options.adoc[] -include::pull-fetch-param.txt[] +include::pull-fetch-param.adoc[] -include::urls-remotes.txt[] +include::urls-remotes.adoc[] -include::merge-strategies.txt[] +include::merge-strategies.adoc[] DEFAULT BEHAVIOUR ----------------- @@ -234,7 +234,7 @@ If you tried a pull which resulted in complex conflicts and would want to start over, you can recover with 'git reset'. -include::transfer-data-leaks.txt[] +include::transfer-data-leaks.adoc[] BUGS ---- diff --git a/Documentation/git-push.txt b/Documentation/git-push.adoc index 9b7cfbc5c1..d1978650d6 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.adoc @@ -432,7 +432,7 @@ further recursion will occur. In this case, "only" is treated as "on-demand". --ipv6:: Use IPv6 addresses only, ignoring IPv4 addresses. -include::urls-remotes.txt[] +include::urls-remotes.adoc[] OUTPUT ------ @@ -695,14 +695,14 @@ Commits A and B would no longer belong to a branch with a symbolic name, and so would be unreachable. As such, these commits would be removed by a `git gc` command on the origin repository. -include::transfer-data-leaks.txt[] +include::transfer-data-leaks.adoc[] CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/push.txt[] +include::config/push.adoc[] GIT --- diff --git a/Documentation/git-quiltimport.txt b/Documentation/git-quiltimport.adoc index 40e02d92eb..40e02d92eb 100644 --- a/Documentation/git-quiltimport.txt +++ b/Documentation/git-quiltimport.adoc diff --git a/Documentation/git-range-diff.txt b/Documentation/git-range-diff.adoc index db0e4279b5..db0e4279b5 100644 --- a/Documentation/git-range-diff.txt +++ b/Documentation/git-range-diff.adoc diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.adoc index 1c48c28996..1c48c28996 100644 --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.adoc diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.adoc index b18cdbc023..956d3048f5 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.adoc @@ -401,7 +401,7 @@ See also INCOMPATIBLE OPTIONS below. + See also INCOMPATIBLE OPTIONS below. -include::rerere-options.txt[] +include::rerere-options.adoc[] -S[<keyid>]:: --gpg-sign[=<keyid>]:: @@ -599,11 +599,11 @@ See also INCOMPATIBLE OPTIONS below. --no-autosquash:: Automatically squash commits with specially formatted messages into previous commits being rebased. If a commit message starts with - "squash! ", "fixup! " or "amend! ", the remainder of the subject line + "squash! ", "fixup! " or "amend! ", the remainder of the title is taken as a commit specifier, which matches a previous commit if it - matches the subject line or the hash of that commit. If no commit + matches the title or the hash of that commit. If no commit matches fully, matches of the specifier with the start of commit - subjects are considered. + titles are considered. + In the rebase todo list, the actions of squash, fixup and amend commits are changed from `pick` to `squash`, `fixup` or `fixup -C`, respectively, and they @@ -613,7 +613,7 @@ be used to review and edit the todo list before proceeding. The recommended way to create commits with squash markers is by using the `--squash`, `--fixup`, `--fixup=amend:` or `--fixup=reword:` options of linkgit:git-commit[1], which take the target commit as an argument and -automatically fill in the subject line of the new commit from that. +automatically fill in the title of the new commit from that. + Setting configuration variable `rebase.autoSquash` to true enables auto-squashing by default for interactive rebase. The `--no-autosquash` @@ -825,7 +825,7 @@ completeness: * State directories: The two backends keep their state in different directories under `.git/` -include::merge-strategies.txt[] +include::merge-strategies.adoc[] NOTES ----- @@ -1107,10 +1107,12 @@ In that case, the fix is easy because 'git rebase' knows to skip changes that are already present in the new upstream (unless `--reapply-cherry-picks` is given). So if you say (assuming you're on 'topic') + ------------ $ git rebase subsystem ------------ you will end up with the fixed history + ------------ o---o---o---o---o---o---o---o master \ @@ -1145,6 +1147,7 @@ of the old 'subsystem', for example: You can then transplant the old `subsystem..topic` to the new tip by saying (for the reflog case, and assuming you are on 'topic' already): + ------------ $ git rebase --onto subsystem subsystem@{1} ------------ @@ -1294,10 +1297,10 @@ merge cmake CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/rebase.txt[] -include::config/sequencer.txt[] +include::config/rebase.adoc[] +include::config/sequencer.adoc[] GIT --- diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.adoc index 20aca92073..20aca92073 100644 --- a/Documentation/git-receive-pack.txt +++ b/Documentation/git-receive-pack.adoc diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.adoc index a929c52982..a929c52982 100644 --- a/Documentation/git-reflog.txt +++ b/Documentation/git-reflog.adoc diff --git a/Documentation/git-refs.txt b/Documentation/git-refs.adoc index 9829984b0a..4d6dc994f9 100644 --- a/Documentation/git-refs.txt +++ b/Documentation/git-refs.adoc @@ -8,9 +8,9 @@ git-refs - Low-level access to refs SYNOPSIS -------- -[verse] -'git refs migrate' --ref-format=<format> [--dry-run] -'git refs verify' [--strict] [--verbose] +[synopsis] +git refs migrate --ref-format=<format> [--no-reflog] [--dry-run] +git refs verify [--strict] [--verbose] DESCRIPTION ----------- @@ -34,7 +34,7 @@ The following options are specific to 'git refs migrate': --ref-format=<format>:: The ref format to migrate the ref store to. Can be one of: + -include::ref-storage-format.txt[] +include::ref-storage-format.adoc[] --dry-run:: Perform the migration, but do not modify the repository. The migrated @@ -43,6 +43,11 @@ include::ref-storage-format.txt[] can be used to double check that the migration works as expected before performing the actual migration. +--reflog:: +--no-reflog:: + Choose between migrating the reflog data to the new backend, + and discarding them. The default is "--reflog", to migrate. + The following options are specific to 'git refs verify': --strict:: diff --git a/Documentation/git-remote-ext.txt b/Documentation/git-remote-ext.adoc index b33ee3c9e8..b33ee3c9e8 100644 --- a/Documentation/git-remote-ext.txt +++ b/Documentation/git-remote-ext.adoc diff --git a/Documentation/git-remote-fd.txt b/Documentation/git-remote-fd.adoc index 1dd2648a79..1dd2648a79 100644 --- a/Documentation/git-remote-fd.txt +++ b/Documentation/git-remote-fd.adoc diff --git a/Documentation/git-remote-helpers.txto b/Documentation/git-remote-helpers.adoco index 6f353ebfd3..6f353ebfd3 100644 --- a/Documentation/git-remote-helpers.txto +++ b/Documentation/git-remote-helpers.adoco diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.adoc index 932a5c3ea4..932a5c3ea4 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.adoc diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.adoc index c902512a9e..5852a5c973 100644 --- a/Documentation/git-repack.txt +++ b/Documentation/git-repack.adoc @@ -9,7 +9,9 @@ git-repack - Pack unpacked objects in a repository SYNOPSIS -------- [verse] -'git repack' [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m] [--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>] [--write-midx] +'git repack' [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m] + [--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>] + [--write-midx] [--name-hash-version=<n>] DESCRIPTION ----------- @@ -249,6 +251,11 @@ linkgit:git-multi-pack-index[1]). Write a multi-pack index (see linkgit:git-multi-pack-index[1]) containing the non-redundant packs. +--name-hash-version=<n>:: + Provide this argument to the underlying `git pack-objects` process. + See linkgit:git-pack-objects[1] for full details. + + CONFIGURATION ------------- diff --git a/Documentation/git-replace.txt b/Documentation/git-replace.adoc index 0a65460adb..0a65460adb 100644 --- a/Documentation/git-replace.txt +++ b/Documentation/git-replace.adoc diff --git a/Documentation/git-replay.txt b/Documentation/git-replay.adoc index 8f3300c683..0b12bf8aa4 100644 --- a/Documentation/git-replay.txt +++ b/Documentation/git-replay.adoc @@ -49,7 +49,7 @@ the new commits (in other words, this mimics a cherry-pick operation). to. See "Specifying Ranges" in linkgit:git-rev-parse[1] and the "Commit Limiting" options below. -include::rev-list-options.txt[] +include::rev-list-options.adoc[] OUTPUT ------ diff --git a/Documentation/git-request-pull.txt b/Documentation/git-request-pull.adoc index 15dcbb6d91..15dcbb6d91 100644 --- a/Documentation/git-request-pull.txt +++ b/Documentation/git-request-pull.adoc diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.adoc index 992b469270..992b469270 100644 --- a/Documentation/git-rerere.txt +++ b/Documentation/git-rerere.adoc diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.adoc index 79ad5643ee..79ad5643ee 100644 --- a/Documentation/git-reset.txt +++ b/Documentation/git-reset.adoc diff --git a/Documentation/git-restore.txt b/Documentation/git-restore.adoc index 975825b44a..751f01b441 100644 --- a/Documentation/git-restore.txt +++ b/Documentation/git-restore.adoc @@ -7,10 +7,10 @@ git-restore - Restore working tree files SYNOPSIS -------- -[verse] -'git restore' [<options>] [--source=<tree>] [--staged] [--worktree] [--] <pathspec>... -'git restore' [<options>] [--source=<tree>] [--staged] [--worktree] --pathspec-from-file=<file> [--pathspec-file-nul] -'git restore' (-p|--patch) [<options>] [--source=<tree>] [--staged] [--worktree] [--] [<pathspec>...] +[synopsis] +git restore [<options>] [--source=<tree>] [--staged] [--worktree] [--] <pathspec>... +git restore [<options>] [--source=<tree>] [--staged] [--worktree] --pathspec-from-file=<file> [--pathspec-file-nul] +git restore (-p|--patch) [<options>] [--source=<tree>] [--staged] [--worktree] [--] [<pathspec>...] DESCRIPTION ----------- @@ -32,8 +32,8 @@ THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE. OPTIONS ------- --s <tree>:: ---source=<tree>:: +`-s <tree>`:: +`--source=<tree>`:: Restore the working tree files with the content from the given tree. It is common to specify the source tree by naming a commit, branch or tag associated with it. @@ -41,79 +41,79 @@ OPTIONS If not specified, the contents are restored from `HEAD` if `--staged` is given, otherwise from the index. + -As a special case, you may use `"A...B"` as a shortcut for the -merge base of `A` and `B` if there is exactly one merge base. You can -leave out at most one of `A` and `B`, in which case it defaults to `HEAD`. +As a special case, you may use `"<rev-A>...<rev-B>"` as a shortcut for the +merge base of _<rev-A>_ and _<rev-B>_ if there is exactly one merge base. You can +leave out at most one of _<rev-A>__ and _<rev-B>_, in which case it defaults to `HEAD`. --p:: ---patch:: +`-p`:: +`--patch`:: Interactively select hunks in the difference between the - restore source and the restore location. See the ``Interactive - Mode'' section of linkgit:git-add[1] to learn how to operate + restore source and the restore location. See the "Interactive + Mode" section of linkgit:git-add[1] to learn how to operate the `--patch` mode. + Note that `--patch` can accept no pathspec and will prompt to restore all modified paths. --W:: ---worktree:: --S:: ---staged:: +`-W`:: +`--worktree`:: +`-S`:: +`--staged`:: Specify the restore location. If neither option is specified, by default the working tree is restored. Specifying `--staged` will only restore the index. Specifying both restores both. --q:: ---quiet:: +`-q`:: +`--quiet`:: Quiet, suppress feedback messages. Implies `--no-progress`. ---progress:: ---no-progress:: +`--progress`:: +`--no-progress`:: Progress status is reported on the standard error stream by default when it is attached to a terminal, unless `--quiet` is specified. This flag enables progress reporting even if not attached to a terminal, regardless of `--quiet`. ---ours:: ---theirs:: +`--ours`:: +`--theirs`:: When restoring files in the working tree from the index, use - stage #2 ('ours') or #3 ('theirs') for unmerged paths. + stage #2 (`ours`) or #3 (`theirs`) for unmerged paths. This option cannot be used when checking out paths from a tree-ish (i.e. with the `--source` option). + -Note that during `git rebase` and `git pull --rebase`, 'ours' and -'theirs' may appear swapped. See the explanation of the same options +Note that during `git rebase` and `git pull --rebase`, `ours` and +`theirs` may appear swapped. See the explanation of the same options in linkgit:git-checkout[1] for details. --m:: ---merge:: +`-m`:: +`--merge`:: When restoring files on the working tree from the index, recreate the conflicted merge in the unmerged paths. This option cannot be used when checking out paths from a tree-ish (i.e. with the `--source` option). ---conflict=<style>:: +`--conflict=<style>`:: The same as `--merge` option above, but changes the way the conflicting hunks are presented, overriding the `merge.conflictStyle` configuration variable. Possible values - are "merge" (default), "diff3", and "zdiff3". + are `merge` (default), `diff3`, and `zdiff3`. ---ignore-unmerged:: +`--ignore-unmerged`:: When restoring files on the working tree from the index, do not abort the operation if there are unmerged entries and neither `--ours`, `--theirs`, `--merge` or `--conflict` is specified. Unmerged paths on the working tree are left alone. ---ignore-skip-worktree-bits:: +`--ignore-skip-worktree-bits`:: In sparse checkout mode, the default is to only update entries - matched by `<pathspec>` and sparse patterns in - $GIT_DIR/info/sparse-checkout. This option ignores the sparse + matched by _<pathspec>_ and sparse patterns in + `$GIT_DIR/info/sparse-checkout`. This option ignores the sparse patterns and unconditionally restores any files in - `<pathspec>`. + _<pathspec>_. ---recurse-submodules:: ---no-recurse-submodules:: - If `<pathspec>` names an active submodule and the restore location +`--recurse-submodules`:: +`--no-recurse-submodules`:: + If _<pathspec>_ names an active submodule and the restore location includes the working tree, the submodule will only be updated if this option is given, in which case its working tree will be restored to the commit recorded in the superproject, and any local @@ -122,30 +122,30 @@ in linkgit:git-checkout[1] for details. not be updated. Just like linkgit:git-checkout[1], this will detach `HEAD` of the submodule. ---overlay:: ---no-overlay:: - In overlay mode, the command never removes files when - restoring. In no-overlay mode, tracked files that do not - appear in the `--source` tree are removed, to make them match - `<tree>` exactly. The default is no-overlay mode. - ---pathspec-from-file=<file>:: - Pathspec is passed in `<file>` instead of commandline args. If - `<file>` is exactly `-` then standard input is used. Pathspec - elements are separated by LF or CR/LF. Pathspec elements can be +`--overlay`:: +`--no-overlay`:: + In overlay mode, never remove files when restoring. In no-overlay mode, + remove tracked files that do not appear in the _<tree>_ of + `--source=<tree>`, to make them match _<tree>_ exactly. The default + is no-overlay mode. + +`--pathspec-from-file=<file>`:: + Pathspec is passed in _<file>_ instead of commandline args. If + _<file>_ is exactly `-` then standard input is used. Pathspec + elements are separated by _LF_ or _CR_/_LF_. Pathspec elements can be quoted as explained for the configuration variable `core.quotePath` (see linkgit:git-config[1]). See also `--pathspec-file-nul` and global `--literal-pathspecs`. ---pathspec-file-nul:: +`--pathspec-file-nul`:: Only meaningful with `--pathspec-from-file`. Pathspec elements are - separated with NUL character and all other characters are taken + separated with _NUL_ character and all other characters are taken literally (including newlines and quotes). -\--:: +`--`:: Do not interpret any more arguments as options. -<pathspec>...:: +`<pathspec>...`:: Limits the paths affected by the operation. + For more details, see the 'pathspec' entry in linkgit:gitglossary[7]. @@ -154,7 +154,7 @@ EXAMPLES -------- The following sequence switches to the `master` branch, reverts the -`Makefile` to two revisions back, deletes hello.c by mistake, and gets +`Makefile` to two revisions back, deletes `hello.c` by mistake, and gets it back from the index. ------------ @@ -165,7 +165,7 @@ $ git restore hello.c <2> ------------ <1> take a file out of another commit -<2> restore hello.c from the index +<2> restore `hello.c` from the index If you want to restore _all_ C source files to match the version in the index, you can say diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.adoc index 2e05c4b510..f582491dd4 100644 --- a/Documentation/git-rev-list.txt +++ b/Documentation/git-rev-list.adoc @@ -15,7 +15,7 @@ DESCRIPTION ----------- :git-rev-list: 1 -include::rev-list-description.txt[] +include::rev-list-description.adoc[] 'rev-list' is an essential Git command, since it provides the ability to build and traverse commit ancestry graphs. For @@ -27,9 +27,9 @@ OPTIONS ------- :git-rev-list: 1 -include::rev-list-options.txt[] +include::rev-list-options.adoc[] -include::pretty-formats.txt[] +include::pretty-formats.adoc[] EXAMPLES -------- diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.adoc index dc12d38534..cc32b4b4f0 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.adoc @@ -351,7 +351,7 @@ Other Options Flags and parameters to be parsed. -include::revisions.txt[] +include::revisions.adoc[] PARSEOPT -------- diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.adoc index 568925db53..ffba365e63 100644 --- a/Documentation/git-revert.txt +++ b/Documentation/git-revert.adoc @@ -112,7 +112,7 @@ effect to your index in a row. Pass the merge strategy-specific option through to the merge strategy. See linkgit:git-merge[1] for details. -include::rerere-options.txt[] +include::rerere-options.adoc[] --reference:: Instead of starting the body of the log message with "This @@ -125,7 +125,7 @@ include::rerere-options.txt[] SEQUENCER SUBCOMMANDS --------------------- -include::sequencer.txt[] +include::sequencer.adoc[] EXAMPLES -------- @@ -155,9 +155,9 @@ Please consider rewording these to be shorter and more unique. CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/revert.txt[] +include::config/revert.adoc[] SEE ALSO -------- diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.adoc index 363a26934f..363a26934f 100644 --- a/Documentation/git-rm.txt +++ b/Documentation/git-rm.adoc diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.adoc index bc3ef45acb..7f223db42d 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.adoc @@ -492,9 +492,9 @@ Information CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/sendemail.txt[] +include::config/sendemail.adoc[] EXAMPLES -------- diff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.adoc index b9e73f2e77..b9e73f2e77 100644 --- a/Documentation/git-send-pack.txt +++ b/Documentation/git-send-pack.adoc diff --git a/Documentation/git-sh-i18n--envsubst.txt b/Documentation/git-sh-i18n--envsubst.adoc index 2ffaf9392e..2ffaf9392e 100644 --- a/Documentation/git-sh-i18n--envsubst.txt +++ b/Documentation/git-sh-i18n--envsubst.adoc diff --git a/Documentation/git-sh-i18n.txt b/Documentation/git-sh-i18n.adoc index 60cf49cb2a..60cf49cb2a 100644 --- a/Documentation/git-sh-i18n.txt +++ b/Documentation/git-sh-i18n.adoc diff --git a/Documentation/git-sh-setup.txt b/Documentation/git-sh-setup.adoc index bdaf6e5fc4..bdaf6e5fc4 100644 --- a/Documentation/git-sh-setup.txt +++ b/Documentation/git-sh-setup.adoc diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.adoc index 11361f33e9..11361f33e9 100644 --- a/Documentation/git-shell.txt +++ b/Documentation/git-shell.adoc diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.adoc index 7d0277d033..d8ab38dcc1 100644 --- a/Documentation/git-shortlog.txt +++ b/Documentation/git-shortlog.adoc @@ -114,7 +114,7 @@ Paths may need to be prefixed with `--` to separate them from options or the revision range, when confusion arises. :git-shortlog: 1 -include::rev-list-options.txt[] +include::rev-list-options.adoc[] MAPPING AUTHORS --------------- diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.adoc index bc31d8b6d3..7e86d54a24 100644 --- a/Documentation/git-show-branch.txt +++ b/Documentation/git-show-branch.adoc @@ -202,9 +202,9 @@ topologically related to each other. CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/showbranch.txt[] +include::config/showbranch.adoc[] GIT --- diff --git a/Documentation/git-show-index.txt b/Documentation/git-show-index.adoc index e49318a5a0..00b3a908cd 100644 --- a/Documentation/git-show-index.txt +++ b/Documentation/git-show-index.adoc @@ -9,7 +9,7 @@ git-show-index - Show packed archive index SYNOPSIS -------- [verse] -'git show-index' [--object-format=<hash-algorithm>] +'git show-index' [--object-format=<hash-algorithm>] < <pack-idx-file> DESCRIPTION @@ -45,7 +45,7 @@ OPTIONS algorithm for the current repository (set by `extensions.objectFormat`), or 'sha1' if no value is set or outside a repository.. + -include::object-format-disclaimer.txt[] +include::object-format-disclaimer.adoc[] GIT --- diff --git a/Documentation/git-show-ref.txt b/Documentation/git-show-ref.adoc index 616d919655..616d919655 100644 --- a/Documentation/git-show-ref.txt +++ b/Documentation/git-show-ref.adoc diff --git a/Documentation/git-show.txt b/Documentation/git-show.adoc index 5eb67439af..51044c814f 100644 --- a/Documentation/git-show.txt +++ b/Documentation/git-show.adoc @@ -39,10 +39,10 @@ OPTIONS For a more complete list of ways to spell object names, see "SPECIFYING REVISIONS" section in linkgit:gitrevisions[7]. -include::pretty-options.txt[] +include::pretty-options.adoc[] -include::pretty-formats.txt[] +include::pretty-formats.adoc[] DIFF FORMATTING @@ -52,9 +52,9 @@ diff output. :git-log: 1 :diff-merges-default: `dense-combined` -include::diff-options.txt[] +include::diff-options.adoc[] -include::diff-generate-patch.txt[] +include::diff-generate-patch.adoc[] EXAMPLES @@ -83,7 +83,7 @@ EXAMPLES DISCUSSION ---------- -include::i18n.txt[] +include::i18n.adoc[] GIT --- diff --git a/Documentation/git-sparse-checkout.txt b/Documentation/git-sparse-checkout.adoc index 529a8edd9c..529a8edd9c 100644 --- a/Documentation/git-sparse-checkout.txt +++ b/Documentation/git-sparse-checkout.adoc diff --git a/Documentation/git-stage.txt b/Documentation/git-stage.adoc index 2f6aaa75b9..2f6aaa75b9 100644 --- a/Documentation/git-stage.txt +++ b/Documentation/git-stage.adoc diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.adoc index 06fb7f1d18..1a5177f498 100644 --- a/Documentation/git-stash.txt +++ b/Documentation/git-stash.adoc @@ -388,9 +388,9 @@ xargs git log --merges --no-walk --grep=WIP CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/stash.txt[] +include::config/stash.adoc[] SEE ALSO diff --git a/Documentation/git-status.txt b/Documentation/git-status.adoc index 9a376886a5..9a376886a5 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.adoc diff --git a/Documentation/git-stripspace.txt b/Documentation/git-stripspace.adoc index a293327581..a293327581 100644 --- a/Documentation/git-stripspace.txt +++ b/Documentation/git-stripspace.adoc diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.adoc index 87d8e0f0c5..87d8e0f0c5 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.adoc diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.adoc index bcf7d84a87..bcf7d84a87 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.adoc diff --git a/Documentation/git-switch.txt b/Documentation/git-switch.adoc index f38e4c8afa..f55315c51e 100644 --- a/Documentation/git-switch.txt +++ b/Documentation/git-switch.adoc @@ -273,9 +273,9 @@ $ git switch -c good-surprises CONFIGURATION ------------- -include::includes/cmd-config-section-all.txt[] +include::includes/cmd-config-section-all.adoc[] -include::config/checkout.txt[] +include::config/checkout.adoc[] SEE ALSO -------- diff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.adoc index 33ca381fde..33ca381fde 100644 --- a/Documentation/git-symbolic-ref.txt +++ b/Documentation/git-symbolic-ref.adoc diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.adoc index 4494729f5e..a4b1c0ec05 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.adoc @@ -391,7 +391,7 @@ For example: $ GIT_COMMITTER_DATE="2006-10-02 10:31" git tag -s v1.0.1 ------------ -include::date-formats.txt[] +include::date-formats.adoc[] FILES ----- @@ -406,7 +406,7 @@ FILES NOTES ----- -include::ref-reachability-filters.txt[] +include::ref-reachability-filters.adoc[] SEE ALSO -------- diff --git a/Documentation/git-tools.txt b/Documentation/git-tools.adoc index d0fec4cddd..d0fec4cddd 100644 --- a/Documentation/git-tools.txt +++ b/Documentation/git-tools.adoc diff --git a/Documentation/git-unpack-file.txt b/Documentation/git-unpack-file.adoc index e9f148a00d..e9f148a00d 100644 --- a/Documentation/git-unpack-file.txt +++ b/Documentation/git-unpack-file.adoc diff --git a/Documentation/git-unpack-objects.txt b/Documentation/git-unpack-objects.adoc index b3de50d710..b3de50d710 100644 --- a/Documentation/git-unpack-objects.txt +++ b/Documentation/git-unpack-objects.adoc diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.adoc index 7128aed540..7128aed540 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.adoc diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.adoc index 9e6935d38d..9e6935d38d 100644 --- a/Documentation/git-update-ref.txt +++ b/Documentation/git-update-ref.adoc diff --git a/Documentation/git-update-server-info.txt b/Documentation/git-update-server-info.adoc index 6bc9b50d89..6bc9b50d89 100644 --- a/Documentation/git-update-server-info.txt +++ b/Documentation/git-update-server-info.adoc diff --git a/Documentation/git-upload-archive.txt b/Documentation/git-upload-archive.adoc index e8eb10baad..e8eb10baad 100644 --- a/Documentation/git-upload-archive.txt +++ b/Documentation/git-upload-archive.adoc diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.adoc index 516d1639d9..516d1639d9 100644 --- a/Documentation/git-upload-pack.txt +++ b/Documentation/git-upload-pack.adoc diff --git a/Documentation/git-var.txt b/Documentation/git-var.adoc index 0680568dfd..0680568dfd 100644 --- a/Documentation/git-var.txt +++ b/Documentation/git-var.adoc diff --git a/Documentation/git-verify-commit.txt b/Documentation/git-verify-commit.adoc index aee4c40eac..aee4c40eac 100644 --- a/Documentation/git-verify-commit.txt +++ b/Documentation/git-verify-commit.adoc diff --git a/Documentation/git-verify-pack.txt b/Documentation/git-verify-pack.adoc index d7e886918a..d7e886918a 100644 --- a/Documentation/git-verify-pack.txt +++ b/Documentation/git-verify-pack.adoc diff --git a/Documentation/git-verify-tag.txt b/Documentation/git-verify-tag.adoc index 81d50ecc4c..81d50ecc4c 100644 --- a/Documentation/git-verify-tag.txt +++ b/Documentation/git-verify-tag.adoc diff --git a/Documentation/git-version.txt b/Documentation/git-version.adoc index 80fa7754a6..80fa7754a6 100644 --- a/Documentation/git-version.txt +++ b/Documentation/git-version.adoc diff --git a/Documentation/git-web--browse.txt b/Documentation/git-web--browse.adoc index f2f996cbe1..f2f996cbe1 100644 --- a/Documentation/git-web--browse.txt +++ b/Documentation/git-web--browse.adoc diff --git a/Documentation/git-whatchanged.txt b/Documentation/git-whatchanged.adoc index 8e55e0bb1e..8e55e0bb1e 100644 --- a/Documentation/git-whatchanged.txt +++ b/Documentation/git-whatchanged.adoc diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.adoc index 8340b7f028..8340b7f028 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.adoc diff --git a/Documentation/git-write-tree.txt b/Documentation/git-write-tree.adoc index f22041a9dc..f22041a9dc 100644 --- a/Documentation/git-write-tree.txt +++ b/Documentation/git-write-tree.adoc diff --git a/Documentation/git.txt b/Documentation/git.adoc index e89a91dd0d..743b7b00e4 100644 --- a/Documentation/git.txt +++ b/Documentation/git.adoc @@ -245,17 +245,17 @@ ancillary user utilities. Main porcelain commands ~~~~~~~~~~~~~~~~~~~~~~~ -include::{build_dir}/cmds-mainporcelain.txt[] +include::{build_dir}/cmds-mainporcelain.adoc[] Ancillary Commands ~~~~~~~~~~~~~~~~~~ Manipulators: -include::{build_dir}/cmds-ancillarymanipulators.txt[] +include::{build_dir}/cmds-ancillarymanipulators.adoc[] Interrogators: -include::{build_dir}/cmds-ancillaryinterrogators.txt[] +include::{build_dir}/cmds-ancillaryinterrogators.adoc[] Interacting with Others @@ -264,7 +264,7 @@ Interacting with Others These commands are to interact with foreign SCM and with other people via patch over e-mail. -include::{build_dir}/cmds-foreignscminterface.txt[] +include::{build_dir}/cmds-foreignscminterface.adoc[] Reset, restore and revert ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -313,13 +313,13 @@ repositories. Manipulation commands ~~~~~~~~~~~~~~~~~~~~~ -include::{build_dir}/cmds-plumbingmanipulators.txt[] +include::{build_dir}/cmds-plumbingmanipulators.adoc[] Interrogation commands ~~~~~~~~~~~~~~~~~~~~~~ -include::{build_dir}/cmds-plumbinginterrogators.txt[] +include::{build_dir}/cmds-plumbinginterrogators.adoc[] In general, the interrogate commands do not touch the files in the working tree. @@ -328,12 +328,12 @@ the working tree. Syncing repositories ~~~~~~~~~~~~~~~~~~~~ -include::{build_dir}/cmds-synchingrepositories.txt[] +include::{build_dir}/cmds-synchingrepositories.adoc[] The following are helper commands used by the above; end users typically do not use them directly. -include::{build_dir}/cmds-synchelpers.txt[] +include::{build_dir}/cmds-synchelpers.adoc[] Internal helper commands @@ -342,14 +342,14 @@ Internal helper commands These are internal helper commands used by other commands; end users typically do not use them directly. -include::{build_dir}/cmds-purehelpers.txt[] +include::{build_dir}/cmds-purehelpers.adoc[] Guides ------ The following documentation pages are guides about Git concepts. -include::{build_dir}/cmds-guide.txt[] +include::{build_dir}/cmds-guide.adoc[] Repository, command and file interfaces --------------------------------------- @@ -358,7 +358,7 @@ This documentation discusses repository and command interfaces which users are expected to interact with directly. See `--user-formats` in linkgit:git-help[1] for more details on the criteria. -include::{build_dir}/cmds-userinterfaces.txt[] +include::{build_dir}/cmds-userinterfaces.adoc[] File formats, protocols and other developer interfaces ------------------------------------------------------ @@ -367,7 +367,7 @@ This documentation discusses file formats, over-the-wire protocols and other git developer interfaces. See `--developer-interfaces` in linkgit:git-help[1]. -include::{build_dir}/cmds-developerinterfaces.txt[] +include::{build_dir}/cmds-developerinterfaces.adoc[] Configuration Mechanism ----------------------- @@ -472,8 +472,9 @@ Environment Variables --------------------- Various Git commands pay attention to environment variables and change their behavior. The environment variables marked as "Boolean" take -their values the same way as Boolean valued configuration variables, e.g. -"true", "yes", "on" and positive numbers are taken as "yes". +their values the same way as Boolean valued configuration variables, i.e., +"true", "yes", "on" and positive numbers are taken as "yes", while "false", +"no", "off", and "0" are taken as "no". Here are the variables: diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.adoc index e6150595af..f20041a323 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.adoc @@ -513,7 +513,7 @@ If the filter command (a string value) is defined via `filter.<driver>.process` then Git can process all blobs with a single filter invocation for the entire life of a single Git command. This is achieved by using the long-running process protocol -(described in technical/long-running-process-protocol.txt). +(described in Documentation/technical/long-running-process-protocol.adoc). When Git encounters the first file that needs to be cleaned or smudged, it starts the filter and performs the handshake. In the handshake, the @@ -531,13 +531,14 @@ must not send any response before it received the content and the final flush packet. Also note that the "value" of a "key=value" pair can contain the "=" character whereas the key would never contain that character. ------------------------- + +----------------------- packet: git> command=smudge packet: git> pathname=path/testfile.dat packet: git> 0000 packet: git> CONTENT packet: git> 0000 ------------------------- +----------------------- The filter is expected to respond with a list of "key=value" pairs terminated with a flush packet. If the filter does not experience @@ -559,6 +560,7 @@ packet: git< 0000 # empty list, keep "status=success" unchanged! If the result content is empty then the filter is expected to respond with a "success" status and a flush packet to signal the empty content. + ------------------------ packet: git< status=success packet: git< 0000 @@ -568,14 +570,16 @@ packet: git< 0000 # empty list, keep "status=success" unchanged! In case the filter cannot or does not want to process the content, it is expected to respond with an "error" status. ------------------------- + +----------------------- packet: git< status=error packet: git< 0000 ------------------------- +----------------------- If the filter experiences an error during processing, then it can send the status "error" after the content was (partially or completely) sent. + ------------------------ packet: git< status=success packet: git< 0000 @@ -589,10 +593,11 @@ In case the filter cannot or does not want to process the content as well as any future content for the lifetime of the Git process, then it is expected to respond with an "abort" status at any point in the protocol. ------------------------- + +----------------------- packet: git< status=abort packet: git< 0000 ------------------------- +----------------------- Git neither stops nor restarts the filter process in case the "error"/"abort" status is set. However, Git sets its exit code @@ -613,7 +618,8 @@ flag "can-delay" after the filter command and pathname. This flag denotes that the filter can delay filtering the current blob (e.g. to compensate network latencies) by responding with no content but with the status "delayed" and a flush packet. ------------------------- + +----------------------- packet: git> command=smudge packet: git> pathname=path/testfile.dat packet: git> can-delay=1 @@ -622,7 +628,7 @@ packet: git> CONTENT packet: git> 0000 packet: git< status=delayed packet: git< 0000 ------------------------- +----------------------- If the filter supports the "delay" capability then it must support the "list_available_blobs" command. If Git sends this command, then the @@ -647,10 +653,12 @@ packet: git< status=success packet: git< 0000 ------------------------ + After Git received the pathnames, it will request the corresponding blobs again. These requests contain a pathname and an empty content section. The filter is expected to respond with the smudged content in the usual way as explained above. + ------------------------ packet: git> command=smudge packet: git> pathname=path/testfile.dat @@ -701,8 +709,8 @@ where the attribute is not in place would normally cause merge conflicts. To prevent these unnecessary merge conflicts, Git can be told to run a -virtual check-out and check-in of all three stages of a file when -resolving a three-way merge by setting the `merge.renormalize` +virtual check-out and check-in of all three stages of each file that +needs a three-way content merge, by setting the `merge.renormalize` configuration variable. This prevents changes caused by check-in conversion from causing spurious merge conflicts when a converted file is merged with an unconverted file. @@ -1166,7 +1174,7 @@ internal merge and the final merge. The merge driver can learn the pathname in which the merged result will be stored via placeholder `%P`. The conflict labels to be used for the common ancestor, local head and other head can be passed by -using '%S', '%X' and '%Y` respectively. +using `%S`, `%X` and `%Y` respectively. `conflict-marker-size` ^^^^^^^^^^^^^^^^^^^^^^ @@ -1177,11 +1185,11 @@ integer has a meaningful effect. For example, this line in `.gitattributes` can be used to tell the merge machinery to leave much longer (instead of the usual 7-character-long) -conflict markers when merging the file `Documentation/git-merge.txt` +conflict markers when merging the file `Documentation/git-merge.adoc` results in a conflict. ------------------------ -Documentation/git-merge.txt conflict-marker-size=32 +Documentation/git-merge.adoc conflict-marker-size=32 ------------------------ diff --git a/Documentation/gitcli.txt b/Documentation/gitcli.adoc index fcd86d2eee..1ea681b59d 100644 --- a/Documentation/gitcli.txt +++ b/Documentation/gitcli.adoc @@ -161,6 +161,23 @@ can use `--no-track` to override that behaviour. The same goes for `--color` and `--no-color`. +Options trump configuration and environment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When there is a configuration variable or an environment variable +that tweak the behaviour of an aspect of a Git command, and also a +command line option that tweaks the same, the command line option +overrides what the configuration and/or environment variable say. + +For example, the `user.name` configuration variable is used to +specify the human-readable name used by the `git commit` command to +record the author and the committer name in a newly created commit. +The `GIT_AUTHOR_NAME` environment variable, if set, takes precedence +when deciding what author name to record. The `--author=<author>` +command line option of the `git commit` command, when given, takes +precedence over these two sources of information. + + Aggregating short options ~~~~~~~~~~~~~~~~~~~~~~~~~ Commands that support the enhanced option parser allow you to aggregate short @@ -192,13 +209,13 @@ $ git foo -o Arg However, this is *NOT* allowed for switches with an optional value, where the 'stuck' form must be used: + ---------------------------- $ git describe --abbrev HEAD # correct $ git describe --abbrev=10 HEAD # correct $ git describe --abbrev 10 HEAD # NOT WHAT YOU MEANT ---------------------------- - NOTES ON FREQUENTLY CONFUSED OPTIONS ------------------------------------ diff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.adoc index 2122aeb976..2122aeb976 100644 --- a/Documentation/gitcore-tutorial.txt +++ b/Documentation/gitcore-tutorial.adoc diff --git a/Documentation/gitcredentials.txt b/Documentation/gitcredentials.adoc index 35a7452c8f..3337bb475d 100644 --- a/Documentation/gitcredentials.txt +++ b/Documentation/gitcredentials.adoc @@ -66,18 +66,7 @@ storage provided by the OS or other programs. Alternatively, a credential-generating helper might generate credentials for certain servers via some API. -To use a helper, you must first select one to use. Git currently -includes the following helpers: - -cache:: - - Cache credentials in memory for a short period of time. See - linkgit:git-credential-cache[1] for details. - -store:: - - Store credentials indefinitely on disk. See - linkgit:git-credential-store[1] for details. +To use a helper, you must first select one to use (see below for a list). You may also have third-party helpers installed; search for `credential-*` in the output of `git help -a`, and consult the @@ -106,6 +95,28 @@ $ git config --global credential.helper foo === Available helpers +Git currently includes the following helpers: + +cache:: + + Cache credentials in memory for a short period of time. See + linkgit:git-credential-cache[1] for details. + +store:: + + Store credentials indefinitely on disk. See + linkgit:git-credential-store[1] for details. + +Popular helpers with secure persistent storage include: + + - git-credential-libsecret (Linux) + + - git-credential-osxkeychain (macOS) + + - git-credential-wincred (Windows) + + - https://github.com/git-ecosystem/git-credential-manager[Git Credential Manager] (cross platform, included in Git for Windows) + The community maintains a comprehensive list of Git credential helpers at https://git-scm.com/doc/credential-helpers. @@ -116,6 +127,12 @@ OAuth credential helper. Initial authentication opens a browser window to the host. Subsequent authentication happens in the background. Many popular Git hosts support OAuth. +Popular helpers with OAuth support include: + + - https://github.com/git-ecosystem/git-credential-manager[Git Credential Manager] (cross platform, included in Git for Windows) + + - https://github.com/hickford/git-credential-oauth[git-credential-oauth] (cross platform, included in many Linux distributions) + CREDENTIAL CONTEXTS ------------------- diff --git a/Documentation/gitcvs-migration.txt b/Documentation/gitcvs-migration.adoc index 1cd1283d0f..1cd1283d0f 100644 --- a/Documentation/gitcvs-migration.txt +++ b/Documentation/gitcvs-migration.adoc diff --git a/Documentation/gitdiffcore.txt b/Documentation/gitdiffcore.adoc index 642c51227b..642c51227b 100644 --- a/Documentation/gitdiffcore.txt +++ b/Documentation/gitdiffcore.adoc diff --git a/Documentation/giteveryday.txt b/Documentation/giteveryday.adoc index 6cfdd0e07b..6cfdd0e07b 100644 --- a/Documentation/giteveryday.txt +++ b/Documentation/giteveryday.adoc diff --git a/Documentation/gitfaq.txt b/Documentation/gitfaq.adoc index f2917d142c..f2917d142c 100644 --- a/Documentation/gitfaq.txt +++ b/Documentation/gitfaq.adoc diff --git a/Documentation/gitformat-bundle.txt b/Documentation/gitformat-bundle.adoc index 1b75cf71ce..1b75cf71ce 100644 --- a/Documentation/gitformat-bundle.txt +++ b/Documentation/gitformat-bundle.adoc diff --git a/Documentation/gitformat-chunk.txt b/Documentation/gitformat-chunk.adoc index 3315df6201..3315df6201 100644 --- a/Documentation/gitformat-chunk.txt +++ b/Documentation/gitformat-chunk.adoc diff --git a/Documentation/gitformat-commit-graph.txt b/Documentation/gitformat-commit-graph.adoc index 14d1631234..14d1631234 100644 --- a/Documentation/gitformat-commit-graph.txt +++ b/Documentation/gitformat-commit-graph.adoc diff --git a/Documentation/gitformat-index.txt b/Documentation/gitformat-index.adoc index 145cace1fe..145cace1fe 100644 --- a/Documentation/gitformat-index.txt +++ b/Documentation/gitformat-index.adoc diff --git a/Documentation/gitformat-pack.txt b/Documentation/gitformat-pack.adoc index d6ae229be5..d6ae229be5 100644 --- a/Documentation/gitformat-pack.txt +++ b/Documentation/gitformat-pack.adoc diff --git a/Documentation/gitformat-signature.txt b/Documentation/gitformat-signature.adoc index d4d3a31f03..d4d3a31f03 100644 --- a/Documentation/gitformat-signature.txt +++ b/Documentation/gitformat-signature.adoc diff --git a/Documentation/gitglossary.txt b/Documentation/gitglossary.adoc index 571f640f5c..0e85be4847 100644 --- a/Documentation/gitglossary.txt +++ b/Documentation/gitglossary.adoc @@ -12,7 +12,7 @@ SYNOPSIS DESCRIPTION ----------- -include::glossary-content.txt[] +include::glossary-content.adoc[] SEE ALSO -------- diff --git a/Documentation/githooks.txt b/Documentation/githooks.adoc index 0397dec64d..0397dec64d 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.adoc diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.adoc index 5e0964ef41..5e0964ef41 100644 --- a/Documentation/gitignore.txt +++ b/Documentation/gitignore.adoc diff --git a/Documentation/gitk.txt b/Documentation/gitk.adoc index 35b3996029..58ce40ddb1 100644 --- a/Documentation/gitk.txt +++ b/Documentation/gitk.adoc @@ -98,7 +98,7 @@ linkgit:git-rev-list[1] for a complete list. (See "History simplification" in linkgit:git-log[1] for a more detailed explanation.) -include::line-range-options.txt[] +include::line-range-options.adoc[] <revision range>:: diff --git a/Documentation/gitmailmap.txt b/Documentation/gitmailmap.adoc index 06f4af93fe..06f4af93fe 100644 --- a/Documentation/gitmailmap.txt +++ b/Documentation/gitmailmap.adoc diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.adoc index d9bec8b187..d9bec8b187 100644 --- a/Documentation/gitmodules.txt +++ b/Documentation/gitmodules.adoc diff --git a/Documentation/gitnamespaces.txt b/Documentation/gitnamespaces.adoc index 1c8d2ecc35..06f4d37efa 100644 --- a/Documentation/gitnamespaces.txt +++ b/Documentation/gitnamespaces.adoc @@ -61,7 +61,7 @@ For a simple local test, you can use linkgit:git-remote-ext[1]: git clone ext::'git --namespace=foo %s /tmp/prefixed.git' ---------- -include::transfer-data-leaks.txt[] +include::transfer-data-leaks.adoc[] GIT --- diff --git a/Documentation/gitpacking.txt b/Documentation/gitpacking.adoc index 321154d4e6..a56596e2d1 100644 --- a/Documentation/gitpacking.txt +++ b/Documentation/gitpacking.adoc @@ -136,7 +136,7 @@ chunks of "stableSize" in order of age. The exact configuration for pseudo-merges is as follows: -include::config/bitmap-pseudo-merge.txt[] +include::config/bitmap-pseudo-merge.adoc[] === Examples diff --git a/Documentation/gitprotocol-capabilities.txt b/Documentation/gitprotocol-capabilities.adoc index 2cf7735be4..2cf7735be4 100644 --- a/Documentation/gitprotocol-capabilities.txt +++ b/Documentation/gitprotocol-capabilities.adoc diff --git a/Documentation/gitprotocol-common.txt b/Documentation/gitprotocol-common.adoc index cdc9d6e707..b4a5316ca4 100644 --- a/Documentation/gitprotocol-common.txt +++ b/Documentation/gitprotocol-common.adoc @@ -21,11 +21,13 @@ ABNF Notation ABNF notation as described by RFC 5234 is used within the protocol documents, except the following replacement core rules are used: + ---- HEXDIG = DIGIT / "a" / "b" / "c" / "d" / "e" / "f" ---- We also define the following common rules: + ---- NUL = %x00 zero-id = 40*"0" diff --git a/Documentation/gitprotocol-http.txt b/Documentation/gitprotocol-http.adoc index ec40a550cc..ec40a550cc 100644 --- a/Documentation/gitprotocol-http.txt +++ b/Documentation/gitprotocol-http.adoc diff --git a/Documentation/gitprotocol-pack.txt b/Documentation/gitprotocol-pack.adoc index 837b691c89..837b691c89 100644 --- a/Documentation/gitprotocol-pack.txt +++ b/Documentation/gitprotocol-pack.adoc diff --git a/Documentation/gitprotocol-v2.txt b/Documentation/gitprotocol-v2.adoc index 1652fef3ae..5598c93e67 100644 --- a/Documentation/gitprotocol-v2.txt +++ b/Documentation/gitprotocol-v2.adoc @@ -184,9 +184,13 @@ form `agent=X`) to notify the client that the server is running version the `agent` capability with a value `Y` (in the form `agent=Y`) in its request to the server (but it MUST NOT do so if the server did not advertise the agent capability). The `X` and `Y` strings may contain any -printable ASCII characters except space (i.e., the byte range 32 < x < -127), and are typically of the form "package/version" (e.g., -"git/1.8.3.1"). The agent strings are purely informative for statistics +printable ASCII characters except space (i.e., the byte range 33 <= x <= +126), and are typically of the form "package/version-os" (e.g., +"git/1.8.3.1-Linux") where `os` is the operating system name (e.g., +"Linux"). `X` and `Y` can be configured using the GIT_USER_AGENT +environment variable and it takes priority. The `os` is +retrieved using the 'sysname' field of the `uname(2)` system call +or its equivalent. The agent strings are purely informative for statistics and debugging purposes, and MUST NOT be used to programmatically assume the presence or absence of particular features. @@ -781,6 +785,60 @@ retrieving the header from a bundle at the indicated URI, and thus save themselves and the server(s) the request(s) needed to inspect the headers of that bundle or bundles. +promisor-remote=<pr-infos> +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The server may advertise some promisor remotes it is using or knows +about to a client which may want to use them as its promisor remotes, +instead of this repository. In this case <pr-infos> should be of the +form: + + pr-infos = pr-info | pr-infos ";" pr-info + + pr-info = "name=" pr-name | "name=" pr-name "," "url=" pr-url + +where `pr-name` is the urlencoded name of a promisor remote, and +`pr-url` the urlencoded URL of that promisor remote. + +In this case, if the client decides to use one or more promisor +remotes the server advertised, it can reply with +"promisor-remote=<pr-names>" where <pr-names> should be of the form: + + pr-names = pr-name | pr-names ";" pr-name + +where `pr-name` is the urlencoded name of a promisor remote the server +advertised and the client accepts. + +Note that, everywhere in this document, `pr-name` MUST be a valid +remote name, and the ';' and ',' characters MUST be encoded if they +appear in `pr-name` or `pr-url`. + +If the server doesn't know any promisor remote that could be good for +a client to use, or prefers a client not to use any promisor remote it +uses or knows about, it shouldn't advertise the "promisor-remote" +capability at all. + +In this case, or if the client doesn't want to use any promisor remote +the server advertised, the client shouldn't advertise the +"promisor-remote" capability at all in its reply. + +The "promisor.advertise" and "promisor.acceptFromServer" configuration +options can be used on the server and client side to control what they +advertise or accept respectively. See the documentation of these +configuration options for more information. + +Note that in the future it would be nice if the "promisor-remote" +protocol capability could be used by the server, when responding to +`git fetch` or `git clone`, to advertise better-connected remotes that +the client can use as promisor remotes, instead of this repository, so +that the client can lazily fetch objects from these other +better-connected remotes. This would require the server to omit in its +response the objects available on the better-connected remotes that +the client has accepted. This hasn't been implemented yet though. So +for now this "promisor-remote" capability is useful only when the +server advertises some promisor remotes it already uses to borrow +objects from. + GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.adoc index d0be008e5e..d0be008e5e 100644 --- a/Documentation/gitremote-helpers.txt +++ b/Documentation/gitremote-helpers.adoc diff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.adoc index fa8b51daf0..7421ef956d 100644 --- a/Documentation/gitrepository-layout.txt +++ b/Documentation/gitrepository-layout.adoc @@ -152,8 +152,9 @@ config.worktree:: working directory in multiple working directory setup (see linkgit:git-worktree[1]). +ifndef::with-breaking-changes[] branches:: - A slightly deprecated way to store shorthands to be used + A deprecated way to store shorthands to be used to specify a URL to 'git fetch', 'git pull' and 'git push'. A file can be stored as `branches/<name>` and then 'name' can be given to these commands in place of @@ -162,7 +163,9 @@ branches:: and not likely to be found in modern repositories. This directory is ignored if $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/branches" will be used instead. - ++ +Git will stop reading remotes from this directory in Git 3.0. +endif::with-breaking-changes[] hooks:: Hooks are customization scripts used by various Git @@ -230,6 +233,7 @@ info/sparse-checkout:: This file stores sparse checkout patterns. See also: linkgit:git-read-tree[1]. +ifndef::with-breaking-changes[] remotes:: Stores shorthands for URL and default refnames for use when interacting with remote repositories via 'git fetch', @@ -238,6 +242,9 @@ remotes:: and not likely to be found in modern repositories. This directory is ignored if $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/remotes" will be used instead. ++ +Git will stop reading remotes from this directory in Git 3.0. +endif::with-breaking-changes[] logs:: Records of changes made to refs are stored in this directory. @@ -292,7 +299,7 @@ worktrees/<id>/locked:: worktrees/<id>/config.worktree:: Working directory specific configuration file. -include::technical/repository-version.txt[] +include::technical/repository-version.adoc[] SEE ALSO -------- diff --git a/Documentation/gitrevisions.txt b/Documentation/gitrevisions.adoc index d407b7dee1..7146117de5 100644 --- a/Documentation/gitrevisions.txt +++ b/Documentation/gitrevisions.adoc @@ -24,7 +24,7 @@ linkgit:git-push[1]) can also take revision parameters which denote other objects than commits, e.g. blobs ("files") or trees ("directories of files"). -include::revisions.txt[] +include::revisions.adoc[] SEE ALSO diff --git a/Documentation/gitsubmodules.txt b/Documentation/gitsubmodules.adoc index f7b5a25a0c..f7b5a25a0c 100644 --- a/Documentation/gitsubmodules.txt +++ b/Documentation/gitsubmodules.adoc diff --git a/Documentation/gittutorial-2.txt b/Documentation/gittutorial-2.adoc index 8bdb7d0bd3..8bdb7d0bd3 100644 --- a/Documentation/gittutorial-2.txt +++ b/Documentation/gittutorial-2.adoc diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.adoc index f89ad30cf6..f89ad30cf6 100644 --- a/Documentation/gittutorial.txt +++ b/Documentation/gittutorial.adoc diff --git a/Documentation/gitweb.txt b/Documentation/gitweb.adoc index 5e2b491ec2..4261f9e235 100644 --- a/Documentation/gitweb.txt +++ b/Documentation/gitweb.adoc @@ -103,6 +103,7 @@ You can generate the projects list index file using the project_index action "Generating projects list using gitweb" section below. Example contents: + ----------------------------------------------------------------------- foo.git Joe+R+Hacker+<joe@example.com> foo/bar.git O+W+Ner+<owner@example.org> @@ -124,6 +125,7 @@ Generating projects list using gitweb We assume that GITWEB_CONFIG has its default Makefile value, namely 'gitweb_config.perl'. Put the following in 'gitweb_make_index.perl' file: + ---------------------------------------------------------------------------- read_config_file("gitweb_config.perl"); $projects_list = $projectroot; @@ -518,12 +520,14 @@ rules. If you use the rewrite rules from the example you *might* also need something like the following in your gitweb configuration file (`/etc/gitweb.conf` following example): + ---------------------------------------------------------------------------- @stylesheets = ("/some/absolute/path/gitweb.css"); $my_uri = "/"; $home_link = "/"; $per_request_config = 1; ---------------------------------------------------------------------------- + Nowadays though gitweb should create HTML base tag when needed (to set base URI for relative links), so it should work automatically. @@ -535,6 +539,7 @@ Apache virtual host and gitweb configuration files in the following way. The virtual host configuration (in Apache configuration file) should look like this: + -------------------------------------------------------------------------- <VirtualHost *:80> ServerName git.example.org @@ -575,9 +580,11 @@ like this: Here actual project root is passed to gitweb via `GITWEB_PROJECT_ROOT` environment variable from a web server, so you need to put the following line in gitweb configuration file (`/etc/gitweb.conf` in above example): + -------------------------------------------------------------------------- $projectroot = $ENV{'GITWEB_PROJECTROOT'} || "/pub/git"; -------------------------------------------------------------------------- + *Note* that this requires to be set for each request, so either `$per_request_config` must be false, or the above must be put in code referenced by `$per_request_config`; @@ -604,9 +611,11 @@ the third and the fourth. PATH_INFO usage ~~~~~~~~~~~~~~~ If you enable PATH_INFO usage in gitweb by putting + ---------------------------------------------------------------------------- $feature{'pathinfo'}{'default'} = [1]; ---------------------------------------------------------------------------- + in your gitweb configuration file, it is possible to set up your server so that it consumes and produces URLs in the form @@ -636,6 +645,7 @@ complementary static files (stylesheet, favicon, JavaScript): </Directory> </VirtualHost> ---------------------------------------------------------------------------- + The rewrite rule guarantees that existing static files will be properly served, whereas any other URL will be passed to gitweb as PATH_INFO parameter. @@ -647,6 +657,7 @@ for fetching" section). A possible workaround for the latter is the following: in your project root dir (e.g. `/pub/git`) have the projects named *without* a .git extension (e.g. `/pub/git/project` instead of `/pub/git/project.git`) and configure Apache as follows: + ---------------------------------------------------------------------------- <VirtualHost *:80> ServerAlias git.example.com diff --git a/Documentation/gitweb.conf.txt b/Documentation/gitweb.conf.adoc index 85983587fc..1348e9b125 100644 --- a/Documentation/gitweb.conf.txt +++ b/Documentation/gitweb.conf.adoc @@ -603,6 +603,7 @@ Many gitweb features can be enabled (or disabled) and configured using the Each `%feature` hash element is a hash reference and has the following structure: + ---------------------------------------------------------------------- "<feature-name>" => { "sub" => <feature-sub-(subroutine)>, @@ -613,6 +614,7 @@ structure: Some features cannot be overridden per project. For those features the structure of appropriate `%feature` hash element has a simpler form: + ---------------------------------------------------------------------- "<feature-name>" => { "override" => 0, diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.adoc index 59305265c5..59305265c5 100644 --- a/Documentation/gitworkflows.txt +++ b/Documentation/gitworkflows.adoc diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.adoc index 575c18f776..575c18f776 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.adoc diff --git a/Documentation/howto/coordinate-embargoed-releases.txt b/Documentation/howto/coordinate-embargoed-releases.adoc index b9cb95e82f..b9cb95e82f 100644 --- a/Documentation/howto/coordinate-embargoed-releases.txt +++ b/Documentation/howto/coordinate-embargoed-releases.adoc diff --git a/Documentation/howto/howto-index.sh b/Documentation/howto/howto-index.sh index eecd123a93..ace49830a8 100755 --- a/Documentation/howto/howto-index.sh +++ b/Documentation/howto/howto-index.sh @@ -9,9 +9,9 @@ people describing how they use Git in their workflow. EOF -for txt +for adoc do - title=$(expr "$txt" : '.*/\(.*\)\.txt$') + title=$(expr "$adoc" : '.*/\(.*\)\.adoc$') from=$(sed -ne ' /^$/q /^From:[ ]/{ @@ -21,7 +21,7 @@ do s/^/by / p } - ' "$txt") + ' "$adoc") abstract=$(sed -ne ' /^Abstract:[ ]/{ @@ -39,13 +39,13 @@ do x p q - }' "$txt") + }' "$adoc") - if grep 'Content-type: text/asciidoc' >/dev/null $txt + if grep 'Content-type: text/asciidoc' >/dev/null $adoc then - file=$(expr "$txt" : '\(.*\)\.txt$').html + file=$(expr "$adoc" : '\(.*\)\.adoc$').html else - file="$txt" + file="$adoc" fi echo "* link:howto/$(basename "$file")[$title] $from diff --git a/Documentation/howto/keep-canonical-history-correct.txt b/Documentation/howto/keep-canonical-history-correct.adoc index e98f03275e..e98f03275e 100644 --- a/Documentation/howto/keep-canonical-history-correct.txt +++ b/Documentation/howto/keep-canonical-history-correct.adoc diff --git a/Documentation/howto/maintain-git.txt b/Documentation/howto/maintain-git.adoc index 45e2599c5d..45e2599c5d 100644 --- a/Documentation/howto/maintain-git.txt +++ b/Documentation/howto/maintain-git.adoc diff --git a/Documentation/howto/meson.build b/Documentation/howto/meson.build index c023c10416..81000028c0 100644 --- a/Documentation/howto/meson.build +++ b/Documentation/howto/meson.build @@ -1,20 +1,20 @@ howto_sources = [ - 'coordinate-embargoed-releases.txt', - 'keep-canonical-history-correct.txt', - 'maintain-git.txt', - 'new-command.txt', - 'rebase-from-internal-branch.txt', - 'rebuild-from-update-hook.txt', - 'recover-corrupted-blob-object.txt', - 'recover-corrupted-object-harder.txt', - 'revert-a-faulty-merge.txt', - 'revert-branch-rebase.txt', - 'separating-topic-branches.txt', - 'setup-git-server-over-http.txt', - 'update-hook-example.txt', - 'use-git-daemon.txt', - 'using-merge-subtree.txt', - 'using-signed-tag-in-pull-request.txt', + 'coordinate-embargoed-releases.adoc', + 'keep-canonical-history-correct.adoc', + 'maintain-git.adoc', + 'new-command.adoc', + 'rebase-from-internal-branch.adoc', + 'rebuild-from-update-hook.adoc', + 'recover-corrupted-blob-object.adoc', + 'recover-corrupted-object-harder.adoc', + 'revert-a-faulty-merge.adoc', + 'revert-branch-rebase.adoc', + 'separating-topic-branches.adoc', + 'setup-git-server-over-http.adoc', + 'update-hook-example.adoc', + 'use-git-daemon.adoc', + 'using-merge-subtree.adoc', + 'using-signed-tag-in-pull-request.adoc', ] howto_index = custom_target( @@ -26,7 +26,7 @@ howto_index = custom_target( env: script_environment, capture: true, input: howto_sources, - output: 'howto-index.txt', + output: 'howto-index.adoc', ) custom_target( @@ -41,7 +41,7 @@ custom_target( foreach howto : howto_sources howto_stripped = custom_target( command: [ - find_program('sed'), + sed, '-e', '1,/^$/d', '@INPUT@', diff --git a/Documentation/howto/new-command.txt b/Documentation/howto/new-command.adoc index 880c51112b..ac73c98be7 100644 --- a/Documentation/howto/new-command.txt +++ b/Documentation/howto/new-command.adoc @@ -48,7 +48,7 @@ binary); this organization makes it easy for people reading the code to find things. See the CodingGuidelines document for other guidance on what we consider -good practice in C and shell, and api-builtin.txt for the support +good practice in C and shell, and builtin.h for the support functions available to built-in commands written in C. What every extension command needs diff --git a/Documentation/howto/rebase-from-internal-branch.txt b/Documentation/howto/rebase-from-internal-branch.adoc index f2e10a7ec8..f2e10a7ec8 100644 --- a/Documentation/howto/rebase-from-internal-branch.txt +++ b/Documentation/howto/rebase-from-internal-branch.adoc diff --git a/Documentation/howto/rebuild-from-update-hook.txt b/Documentation/howto/rebuild-from-update-hook.adoc index db219f5c07..db219f5c07 100644 --- a/Documentation/howto/rebuild-from-update-hook.txt +++ b/Documentation/howto/rebuild-from-update-hook.adoc diff --git a/Documentation/howto/recover-corrupted-blob-object.txt b/Documentation/howto/recover-corrupted-blob-object.adoc index 1b3b188d3c..1b3b188d3c 100644 --- a/Documentation/howto/recover-corrupted-blob-object.txt +++ b/Documentation/howto/recover-corrupted-blob-object.adoc diff --git a/Documentation/howto/recover-corrupted-object-harder.txt b/Documentation/howto/recover-corrupted-object-harder.adoc index 5efb4fe81f..5efb4fe81f 100644 --- a/Documentation/howto/recover-corrupted-object-harder.txt +++ b/Documentation/howto/recover-corrupted-object-harder.adoc diff --git a/Documentation/howto/revert-a-faulty-merge.txt b/Documentation/howto/revert-a-faulty-merge.adoc index 19f59cc888..19f59cc888 100644 --- a/Documentation/howto/revert-a-faulty-merge.txt +++ b/Documentation/howto/revert-a-faulty-merge.adoc diff --git a/Documentation/howto/revert-branch-rebase.txt b/Documentation/howto/revert-branch-rebase.adoc index a3e5595a56..a3e5595a56 100644 --- a/Documentation/howto/revert-branch-rebase.txt +++ b/Documentation/howto/revert-branch-rebase.adoc diff --git a/Documentation/howto/separating-topic-branches.txt b/Documentation/howto/separating-topic-branches.adoc index 81be0d6115..81be0d6115 100644 --- a/Documentation/howto/separating-topic-branches.txt +++ b/Documentation/howto/separating-topic-branches.adoc diff --git a/Documentation/howto/setup-git-server-over-http.txt b/Documentation/howto/setup-git-server-over-http.adoc index bfe6f9b500..bfe6f9b500 100644 --- a/Documentation/howto/setup-git-server-over-http.txt +++ b/Documentation/howto/setup-git-server-over-http.adoc diff --git a/Documentation/howto/update-hook-example.txt b/Documentation/howto/update-hook-example.adoc index 4e727deedd..4e727deedd 100644 --- a/Documentation/howto/update-hook-example.txt +++ b/Documentation/howto/update-hook-example.adoc diff --git a/Documentation/howto/use-git-daemon.txt b/Documentation/howto/use-git-daemon.adoc index 2cad9b3ca5..2cad9b3ca5 100644 --- a/Documentation/howto/use-git-daemon.txt +++ b/Documentation/howto/use-git-daemon.adoc diff --git a/Documentation/howto/using-merge-subtree.txt b/Documentation/howto/using-merge-subtree.adoc index 3bd581ac35..3bd581ac35 100644 --- a/Documentation/howto/using-merge-subtree.txt +++ b/Documentation/howto/using-merge-subtree.adoc diff --git a/Documentation/howto/using-signed-tag-in-pull-request.txt b/Documentation/howto/using-signed-tag-in-pull-request.adoc index bbf040eda8..bbf040eda8 100644 --- a/Documentation/howto/using-signed-tag-in-pull-request.txt +++ b/Documentation/howto/using-signed-tag-in-pull-request.adoc diff --git a/Documentation/i18n.txt b/Documentation/i18n.adoc index 3a866af4a4..baff780a7e 100644 --- a/Documentation/i18n.txt +++ b/Documentation/i18n.adoc @@ -34,7 +34,7 @@ project find it more convenient to use legacy encodings, Git does not forbid it. However, there are a few things to keep in mind. -. 'git commit' and 'git commit-tree' issue +. `git commit` and `git commit-tree` issue a warning if the commit log message given to it does not look like a valid UTF-8 string, unless you explicitly say your project uses a legacy encoding. The way to say this is to @@ -50,7 +50,7 @@ of `i18n.commitEncoding` in their `encoding` header. This is to help other people who look at them later. Lack of this header implies that the commit log message is encoded in UTF-8. -. 'git log', 'git show', 'git blame' and friends look at the +. `git log`, `git show`, `git blame` and friends look at the `encoding` header of a commit object, and try to re-code the log message into UTF-8 unless otherwise specified. You can specify the desired output encoding with diff --git a/Documentation/includes/cmd-config-section-all.txt b/Documentation/includes/cmd-config-section-all.adoc index 296a239f2a..296a239f2a 100644 --- a/Documentation/includes/cmd-config-section-all.txt +++ b/Documentation/includes/cmd-config-section-all.adoc diff --git a/Documentation/includes/cmd-config-section-rest.txt b/Documentation/includes/cmd-config-section-rest.adoc index b1e7682c1d..b1e7682c1d 100644 --- a/Documentation/includes/cmd-config-section-rest.txt +++ b/Documentation/includes/cmd-config-section-rest.adoc diff --git a/Documentation/install-webdoc.sh b/Documentation/install-webdoc.sh index ed8b4ff3e5..b237b311c3 100755 --- a/Documentation/install-webdoc.sh +++ b/Documentation/install-webdoc.sh @@ -3,10 +3,10 @@ T="$1" for h in \ - *.txt *.html \ - howto/*.txt howto/*.html \ - technical/*.txt technical/*.html \ - RelNotes/*.txt *.css + *.adoc *.html \ + howto/*.adoc howto/*.html \ + technical/*.adoc technical/*.html \ + RelNotes/*.adoc *.css do if test ! -f "$h" then @@ -24,13 +24,13 @@ do done strip_leading=$(echo "$T/" | sed -e 's|.|.|g') for th in \ - "$T"/*.html "$T"/*.txt \ - "$T"/howto/*.txt "$T"/howto/*.html \ - "$T"/technical/*.txt "$T"/technical/*.html + "$T"/*.html "$T"/*.adoc \ + "$T"/howto/*.adoc "$T"/howto/*.html \ + "$T"/technical/*.adoc "$T"/technical/*.html do h=$(expr "$th" : "$strip_leading"'\(.*\)') case "$h" in - RelNotes-*.txt | index.html) continue ;; + RelNotes-*.adoc | index.html) continue ;; esac test -f "$h" && continue echo >&2 "# rm -f $th" diff --git a/Documentation/line-range-format.txt b/Documentation/line-range-format.adoc index 9b51e9fb66..9b51e9fb66 100644 --- a/Documentation/line-range-format.txt +++ b/Documentation/line-range-format.adoc diff --git a/Documentation/line-range-options.txt b/Documentation/line-range-options.adoc index 8e295a62b8..f275df3b69 100644 --- a/Documentation/line-range-options.txt +++ b/Documentation/line-range-options.adoc @@ -12,4 +12,4 @@ (namely `--raw`, `--numstat`, `--shortstat`, `--dirstat`, `--summary`, `--name-only`, `--name-status`, `--check`) are not currently implemented. + -include::line-range-format.txt[] +include::line-range-format.adoc[] diff --git a/Documentation/lint-gitlink.perl b/Documentation/lint-gitlink.perl index 1c61dd9512..aea564dad7 100755 --- a/Documentation/lint-gitlink.perl +++ b/Documentation/lint-gitlink.perl @@ -5,7 +5,7 @@ use warnings; # Parse arguments, a simple state machine for input like: # -# <file-to-check.txt> <valid-files-to-link-to> --section=1 git.txt git-add.txt [...] --to-lint git-add.txt a-file.txt [...] +# <file-to-check.adoc> <valid-files-to-link-to> --section=1 git.adoc git-add.adoc [...] --to-lint git-add.adoc a-file.adoc [...] my %TXT; my %SECTION; my $section; @@ -17,7 +17,7 @@ for my $arg (@ARGV) { next; } - my ($name) = $arg =~ /^(.*?)\.txt$/s; + my ($name) = $arg =~ /^(.*?)\.adoc$/s; unless (defined $section) { $TXT{$name} = $arg; next; diff --git a/Documentation/lint-manpages.sh b/Documentation/lint-manpages.sh index 92cfc0a15a..a0ea572382 100755 --- a/Documentation/lint-manpages.sh +++ b/Documentation/lint-manpages.sh @@ -31,7 +31,7 @@ check_missing_docs () ( git-?*--?* ) continue ;; esac - if ! test -f "$v.txt" + if ! test -f "$v.adoc" then echo "no doc: $v" ret=1 @@ -63,9 +63,9 @@ check_extraneous_docs () { -e 's/[ ].*//' \ -e 's/^/listed /' ../command-list.txt make print-man1 | - grep '\.txt$' | + grep '\.adoc$' | sed -e 's|^|documented |' \ - -e 's/\.txt//' + -e 's/\.adoc//' ) | ( all_commands="$(printf "%s " "$ALL_COMMANDS" "$BUILT_INS" "$EXCLUDED_PROGRAMS" | tr '\n' ' ')" ret=0 diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.adoc index 3eaefc4e94..0022185201 100644 --- a/Documentation/merge-options.txt +++ b/Documentation/merge-options.adoc @@ -102,7 +102,7 @@ endif::git-pull[] With --no-log do not list one-line descriptions from the actual commits being merged. -include::signoff-option.txt[] +include::signoff-option.adoc[] --stat:: -n:: diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.adoc index 5fc54ec060..59f5ae36cc 100644 --- a/Documentation/merge-strategies.txt +++ b/Documentation/merge-strategies.adoc @@ -22,6 +22,13 @@ ort:: was written as a replacement for the previous default algorithm, `recursive`. + +In the case where the path is a submodule, if the submodule commit used on +one side of the merge is a descendant of the submodule commit used on the +other side of the merge, Git attempts to fast-forward to the +descendant. Otherwise, Git will treat this case as a conflict, suggesting +as a resolution a submodule commit that is descendant of the conflicting +ones, if one exists. ++ The 'ort' strategy can take the following options: ours;; @@ -56,7 +63,7 @@ ignore-cr-at-eol;; renormalize;; This runs a virtual check-out and check-in of all three stages - of a file when resolving a three-way merge. This option is + of any file which needs a three-way merge. This option is meant to be used when merging branches with different clean filters or end-of-line normalization rules. See "Merging branches with differing checkin/checkout attributes" in @@ -75,6 +82,11 @@ find-renames[=<n>];; rename-threshold=<n>;; Deprecated synonym for `find-renames=<n>`. +no-renames;; + Turn off rename detection. This overrides the `merge.renames` + configuration variable. + See also linkgit:git-diff[1] `--no-renames`. + subtree[=<path>];; This option is a more advanced form of 'subtree' strategy, where the strategy makes a guess on how two trees must be shifted to @@ -96,8 +108,11 @@ recursive:: the default strategy for resolving two heads from Git v0.99.9k until v2.33.0. + +For a path that is a submodule, the same caution as 'ort' applies to this +strategy. ++ The 'recursive' strategy takes the same options as 'ort'. However, -there are three additional options that 'ort' ignores (not documented +there are two additional options that 'ort' ignores (not documented above) that are potentially useful with the 'recursive' strategy: patience;; @@ -111,11 +126,6 @@ diff-algorithm=[patience|minimal|histogram|myers];; specifically uses `diff-algorithm=histogram`, while `recursive` defaults to the `diff.algorithm` config setting. -no-renames;; - Turn off rename detection. This overrides the `merge.renames` - configuration variable. - See also linkgit:git-diff[1] `--no-renames`. - resolve:: This can only resolve two heads (i.e. the current branch and another branch you pulled from) using a 3-way merge diff --git a/Documentation/mergetools/vimdiff.txt b/Documentation/mergetools/vimdiff.adoc index befa86d692..befa86d692 100644 --- a/Documentation/mergetools/vimdiff.txt +++ b/Documentation/mergetools/vimdiff.adoc diff --git a/Documentation/meson.build b/Documentation/meson.build index 2a26fa8a5f..5e556ce360 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -1,214 +1,223 @@ manpages = { # Category 1. - 'git-add.txt' : 1, - 'git-am.txt' : 1, - 'git-annotate.txt' : 1, - 'git-apply.txt' : 1, - 'git-archimport.txt' : 1, - 'git-archive.txt' : 1, - 'git-bisect.txt' : 1, - 'git-blame.txt' : 1, - 'git-branch.txt' : 1, - 'git-bugreport.txt' : 1, - 'git-bundle.txt' : 1, - 'git-cat-file.txt' : 1, - 'git-check-attr.txt' : 1, - 'git-check-ignore.txt' : 1, - 'git-check-mailmap.txt' : 1, - 'git-checkout-index.txt' : 1, - 'git-checkout.txt' : 1, - 'git-check-ref-format.txt' : 1, - 'git-cherry-pick.txt' : 1, - 'git-cherry.txt' : 1, - 'git-citool.txt' : 1, - 'git-clean.txt' : 1, - 'git-clone.txt' : 1, - 'git-column.txt' : 1, - 'git-commit-graph.txt' : 1, - 'git-commit-tree.txt' : 1, - 'git-commit.txt' : 1, - 'git-config.txt' : 1, - 'git-count-objects.txt' : 1, - 'git-credential-cache--daemon.txt' : 1, - 'git-credential-cache.txt' : 1, - 'git-credential-store.txt' : 1, - 'git-credential.txt' : 1, - 'git-cvsexportcommit.txt' : 1, - 'git-cvsimport.txt' : 1, - 'git-cvsserver.txt' : 1, - 'git-daemon.txt' : 1, - 'git-describe.txt' : 1, - 'git-diagnose.txt' : 1, - 'git-diff-files.txt' : 1, - 'git-diff-index.txt' : 1, - 'git-difftool.txt' : 1, - 'git-diff-tree.txt' : 1, - 'git-diff.txt' : 1, - 'git-fast-export.txt' : 1, - 'git-fast-import.txt' : 1, - 'git-fetch-pack.txt' : 1, - 'git-fetch.txt' : 1, - 'git-filter-branch.txt' : 1, - 'git-fmt-merge-msg.txt' : 1, - 'git-for-each-ref.txt' : 1, - 'git-for-each-repo.txt' : 1, - 'git-format-patch.txt' : 1, - 'git-fsck-objects.txt' : 1, - 'git-fsck.txt' : 1, - 'git-fsmonitor--daemon.txt' : 1, - 'git-gc.txt' : 1, - 'git-get-tar-commit-id.txt' : 1, - 'git-grep.txt' : 1, - 'git-gui.txt' : 1, - 'git-hash-object.txt' : 1, - 'git-help.txt' : 1, - 'git-hook.txt' : 1, - 'git-http-backend.txt' : 1, - 'git-http-fetch.txt' : 1, - 'git-http-push.txt' : 1, - 'git-imap-send.txt' : 1, - 'git-index-pack.txt' : 1, - 'git-init-db.txt' : 1, - 'git-init.txt' : 1, - 'git-instaweb.txt' : 1, - 'git-interpret-trailers.txt' : 1, - 'git-log.txt' : 1, - 'git-ls-files.txt' : 1, - 'git-ls-remote.txt' : 1, - 'git-ls-tree.txt' : 1, - 'git-mailinfo.txt' : 1, - 'git-mailsplit.txt' : 1, - 'git-maintenance.txt' : 1, - 'git-merge-base.txt' : 1, - 'git-merge-file.txt' : 1, - 'git-merge-index.txt' : 1, - 'git-merge-one-file.txt' : 1, - 'git-mergetool--lib.txt' : 1, - 'git-mergetool.txt' : 1, - 'git-merge-tree.txt' : 1, - 'git-merge.txt' : 1, - 'git-mktag.txt' : 1, - 'git-mktree.txt' : 1, - 'git-multi-pack-index.txt' : 1, - 'git-mv.txt' : 1, - 'git-name-rev.txt' : 1, - 'git-notes.txt' : 1, - 'git-p4.txt' : 1, - 'git-pack-objects.txt' : 1, - 'git-pack-redundant.txt' : 1, - 'git-pack-refs.txt' : 1, - 'git-patch-id.txt' : 1, - 'git-prune-packed.txt' : 1, - 'git-prune.txt' : 1, - 'git-pull.txt' : 1, - 'git-push.txt' : 1, - 'git-quiltimport.txt' : 1, - 'git-range-diff.txt' : 1, - 'git-read-tree.txt' : 1, - 'git-rebase.txt' : 1, - 'git-receive-pack.txt' : 1, - 'git-reflog.txt' : 1, - 'git-refs.txt' : 1, - 'git-remote-ext.txt' : 1, - 'git-remote-fd.txt' : 1, - 'git-remote.txt' : 1, - 'git-repack.txt' : 1, - 'git-replace.txt' : 1, - 'git-replay.txt' : 1, - 'git-request-pull.txt' : 1, - 'git-rerere.txt' : 1, - 'git-reset.txt' : 1, - 'git-restore.txt' : 1, - 'git-revert.txt' : 1, - 'git-rev-list.txt' : 1, - 'git-rev-parse.txt' : 1, - 'git-rm.txt' : 1, - 'git-send-email.txt' : 1, - 'git-send-pack.txt' : 1, - 'git-shell.txt' : 1, - 'git-sh-i18n--envsubst.txt' : 1, - 'git-sh-i18n.txt' : 1, - 'git-shortlog.txt' : 1, - 'git-show-branch.txt' : 1, - 'git-show-index.txt' : 1, - 'git-show-ref.txt' : 1, - 'git-show.txt' : 1, - 'git-sh-setup.txt' : 1, - 'git-sparse-checkout.txt' : 1, - 'git-stage.txt' : 1, - 'git-stash.txt' : 1, - 'git-status.txt' : 1, - 'git-stripspace.txt' : 1, - 'git-submodule.txt' : 1, - 'git-svn.txt' : 1, - 'git-switch.txt' : 1, - 'git-symbolic-ref.txt' : 1, - 'git-tag.txt' : 1, - 'git-unpack-file.txt' : 1, - 'git-unpack-objects.txt' : 1, - 'git-update-index.txt' : 1, - 'git-update-ref.txt' : 1, - 'git-update-server-info.txt' : 1, - 'git-upload-archive.txt' : 1, - 'git-upload-pack.txt' : 1, - 'git-var.txt' : 1, - 'git-verify-commit.txt' : 1, - 'git-verify-pack.txt' : 1, - 'git-verify-tag.txt' : 1, - 'git-version.txt' : 1, - 'git-web--browse.txt' : 1, - 'git-whatchanged.txt' : 1, - 'git-worktree.txt' : 1, - 'git-write-tree.txt' : 1, - 'git.txt' : 1, - 'gitk.txt' : 1, - 'gitweb.txt' : 1, - 'scalar.txt' : 1, + 'git-add.adoc' : 1, + 'git-am.adoc' : 1, + 'git-annotate.adoc' : 1, + 'git-apply.adoc' : 1, + 'git-archimport.adoc' : 1, + 'git-archive.adoc' : 1, + 'git-backfill.adoc' : 1, + 'git-bisect.adoc' : 1, + 'git-blame.adoc' : 1, + 'git-branch.adoc' : 1, + 'git-bugreport.adoc' : 1, + 'git-bundle.adoc' : 1, + 'git-cat-file.adoc' : 1, + 'git-check-attr.adoc' : 1, + 'git-check-ignore.adoc' : 1, + 'git-check-mailmap.adoc' : 1, + 'git-checkout-index.adoc' : 1, + 'git-checkout.adoc' : 1, + 'git-check-ref-format.adoc' : 1, + 'git-cherry-pick.adoc' : 1, + 'git-cherry.adoc' : 1, + 'git-citool.adoc' : 1, + 'git-clean.adoc' : 1, + 'git-clone.adoc' : 1, + 'git-column.adoc' : 1, + 'git-commit-graph.adoc' : 1, + 'git-commit-tree.adoc' : 1, + 'git-commit.adoc' : 1, + 'git-config.adoc' : 1, + 'git-count-objects.adoc' : 1, + 'git-credential-cache--daemon.adoc' : 1, + 'git-credential-cache.adoc' : 1, + 'git-credential-store.adoc' : 1, + 'git-credential.adoc' : 1, + 'git-cvsexportcommit.adoc' : 1, + 'git-cvsimport.adoc' : 1, + 'git-cvsserver.adoc' : 1, + 'git-daemon.adoc' : 1, + 'git-describe.adoc' : 1, + 'git-diagnose.adoc' : 1, + 'git-diff-files.adoc' : 1, + 'git-diff-index.adoc' : 1, + 'git-diff-pairs.adoc' : 1, + 'git-difftool.adoc' : 1, + 'git-diff-tree.adoc' : 1, + 'git-diff.adoc' : 1, + 'git-fast-export.adoc' : 1, + 'git-fast-import.adoc' : 1, + 'git-fetch-pack.adoc' : 1, + 'git-fetch.adoc' : 1, + 'git-filter-branch.adoc' : 1, + 'git-fmt-merge-msg.adoc' : 1, + 'git-for-each-ref.adoc' : 1, + 'git-for-each-repo.adoc' : 1, + 'git-format-patch.adoc' : 1, + 'git-fsck-objects.adoc' : 1, + 'git-fsck.adoc' : 1, + 'git-fsmonitor--daemon.adoc' : 1, + 'git-gc.adoc' : 1, + 'git-get-tar-commit-id.adoc' : 1, + 'git-grep.adoc' : 1, + 'git-gui.adoc' : 1, + 'git-hash-object.adoc' : 1, + 'git-help.adoc' : 1, + 'git-hook.adoc' : 1, + 'git-http-backend.adoc' : 1, + 'git-http-fetch.adoc' : 1, + 'git-http-push.adoc' : 1, + 'git-imap-send.adoc' : 1, + 'git-index-pack.adoc' : 1, + 'git-init-db.adoc' : 1, + 'git-init.adoc' : 1, + 'git-instaweb.adoc' : 1, + 'git-interpret-trailers.adoc' : 1, + 'git-log.adoc' : 1, + 'git-ls-files.adoc' : 1, + 'git-ls-remote.adoc' : 1, + 'git-ls-tree.adoc' : 1, + 'git-mailinfo.adoc' : 1, + 'git-mailsplit.adoc' : 1, + 'git-maintenance.adoc' : 1, + 'git-merge-base.adoc' : 1, + 'git-merge-file.adoc' : 1, + 'git-merge-index.adoc' : 1, + 'git-merge-one-file.adoc' : 1, + 'git-mergetool--lib.adoc' : 1, + 'git-mergetool.adoc' : 1, + 'git-merge-tree.adoc' : 1, + 'git-merge.adoc' : 1, + 'git-mktag.adoc' : 1, + 'git-mktree.adoc' : 1, + 'git-multi-pack-index.adoc' : 1, + 'git-mv.adoc' : 1, + 'git-name-rev.adoc' : 1, + 'git-notes.adoc' : 1, + 'git-p4.adoc' : 1, + 'git-pack-objects.adoc' : 1, + 'git-pack-refs.adoc' : 1, + 'git-patch-id.adoc' : 1, + 'git-prune-packed.adoc' : 1, + 'git-prune.adoc' : 1, + 'git-pull.adoc' : 1, + 'git-push.adoc' : 1, + 'git-quiltimport.adoc' : 1, + 'git-range-diff.adoc' : 1, + 'git-read-tree.adoc' : 1, + 'git-rebase.adoc' : 1, + 'git-receive-pack.adoc' : 1, + 'git-reflog.adoc' : 1, + 'git-refs.adoc' : 1, + 'git-remote-ext.adoc' : 1, + 'git-remote-fd.adoc' : 1, + 'git-remote.adoc' : 1, + 'git-repack.adoc' : 1, + 'git-replace.adoc' : 1, + 'git-replay.adoc' : 1, + 'git-request-pull.adoc' : 1, + 'git-rerere.adoc' : 1, + 'git-reset.adoc' : 1, + 'git-restore.adoc' : 1, + 'git-revert.adoc' : 1, + 'git-rev-list.adoc' : 1, + 'git-rev-parse.adoc' : 1, + 'git-rm.adoc' : 1, + 'git-send-email.adoc' : 1, + 'git-send-pack.adoc' : 1, + 'git-shell.adoc' : 1, + 'git-sh-i18n--envsubst.adoc' : 1, + 'git-sh-i18n.adoc' : 1, + 'git-shortlog.adoc' : 1, + 'git-show-branch.adoc' : 1, + 'git-show-index.adoc' : 1, + 'git-show-ref.adoc' : 1, + 'git-show.adoc' : 1, + 'git-sh-setup.adoc' : 1, + 'git-sparse-checkout.adoc' : 1, + 'git-stage.adoc' : 1, + 'git-stash.adoc' : 1, + 'git-status.adoc' : 1, + 'git-stripspace.adoc' : 1, + 'git-submodule.adoc' : 1, + 'git-svn.adoc' : 1, + 'git-switch.adoc' : 1, + 'git-symbolic-ref.adoc' : 1, + 'git-tag.adoc' : 1, + 'git-unpack-file.adoc' : 1, + 'git-unpack-objects.adoc' : 1, + 'git-update-index.adoc' : 1, + 'git-update-ref.adoc' : 1, + 'git-update-server-info.adoc' : 1, + 'git-upload-archive.adoc' : 1, + 'git-upload-pack.adoc' : 1, + 'git-var.adoc' : 1, + 'git-verify-commit.adoc' : 1, + 'git-verify-pack.adoc' : 1, + 'git-verify-tag.adoc' : 1, + 'git-version.adoc' : 1, + 'git-web--browse.adoc' : 1, + 'git-whatchanged.adoc' : 1, + 'git-worktree.adoc' : 1, + 'git-write-tree.adoc' : 1, + 'git.adoc' : 1, + 'gitk.adoc' : 1, + 'gitweb.adoc' : 1, + 'scalar.adoc' : 1, # Category 5. - 'gitattributes.txt' : 5, - 'gitformat-bundle.txt' : 5, - 'gitformat-chunk.txt' : 5, - 'gitformat-commit-graph.txt' : 5, - 'gitformat-index.txt' : 5, - 'gitformat-pack.txt' : 5, - 'gitformat-signature.txt' : 5, - 'githooks.txt' : 5, - 'gitignore.txt' : 5, - 'gitmailmap.txt' : 5, - 'gitmodules.txt' : 5, - 'gitprotocol-capabilities.txt' : 5, - 'gitprotocol-common.txt' : 5, - 'gitprotocol-http.txt' : 5, - 'gitprotocol-pack.txt' : 5, - 'gitprotocol-v2.txt' : 5, - 'gitrepository-layout.txt' : 5, - 'gitweb.conf.txt' : 5, + 'gitattributes.adoc' : 5, + 'gitformat-bundle.adoc' : 5, + 'gitformat-chunk.adoc' : 5, + 'gitformat-commit-graph.adoc' : 5, + 'gitformat-index.adoc' : 5, + 'gitformat-pack.adoc' : 5, + 'gitformat-signature.adoc' : 5, + 'githooks.adoc' : 5, + 'gitignore.adoc' : 5, + 'gitmailmap.adoc' : 5, + 'gitmodules.adoc' : 5, + 'gitprotocol-capabilities.adoc' : 5, + 'gitprotocol-common.adoc' : 5, + 'gitprotocol-http.adoc' : 5, + 'gitprotocol-pack.adoc' : 5, + 'gitprotocol-v2.adoc' : 5, + 'gitrepository-layout.adoc' : 5, + 'gitweb.conf.adoc' : 5, # Category 7. - 'gitcli.txt' : 7, - 'gitcore-tutorial.txt' : 7, - 'gitcredentials.txt' : 7, - 'gitcvs-migration.txt' : 7, - 'gitdiffcore.txt' : 7, - 'giteveryday.txt' : 7, - 'gitfaq.txt' : 7, - 'gitglossary.txt' : 7, - 'gitpacking.txt' : 7, - 'gitnamespaces.txt' : 7, - 'gitremote-helpers.txt' : 7, - 'gitrevisions.txt' : 7, - 'gitsubmodules.txt' : 7, - 'gittutorial-2.txt' : 7, - 'gittutorial.txt' : 7, - 'gitworkflows.txt' : 7, + 'gitcli.adoc' : 7, + 'gitcore-tutorial.adoc' : 7, + 'gitcredentials.adoc' : 7, + 'gitcvs-migration.adoc' : 7, + 'gitdiffcore.adoc' : 7, + 'giteveryday.adoc' : 7, + 'gitfaq.adoc' : 7, + 'gitglossary.adoc' : 7, + 'gitpacking.adoc' : 7, + 'gitnamespaces.adoc' : 7, + 'gitremote-helpers.adoc' : 7, + 'gitrevisions.adoc' : 7, + 'gitsubmodules.adoc' : 7, + 'gittutorial-2.adoc' : 7, + 'gittutorial.adoc' : 7, + 'gitworkflows.adoc' : 7, } +manpages_breaking_changes = { + 'git-pack-redundant.adoc' : 1, +} + +if not get_option('breaking_changes') + manpages += manpages_breaking_changes +endif + docs_backend = get_option('docs_backend') if docs_backend == 'auto' - if find_program('asciidoc', required: false).found() + if find_program('asciidoc', dirs: program_path, required: false).found() docs_backend = 'asciidoc' - elif find_program('asciidoctor', required: false).found() + elif find_program('asciidoctor', dirs: program_path, required: false).found() docs_backend = 'asciidoctor' else error('Neither asciidoc nor asciidoctor were found.') @@ -216,7 +225,7 @@ if docs_backend == 'auto' endif if docs_backend == 'asciidoc' - asciidoc = find_program('asciidoc', required: true) + asciidoc = find_program('asciidoc', dirs: program_path) asciidoc_html = 'xhtml11' asciidoc_docbook = 'docbook' xmlto_extra = [ ] @@ -245,7 +254,7 @@ if docs_backend == 'asciidoc' asciidoc_conf, ] elif docs_backend == 'asciidoctor' - asciidoctor = find_program('asciidoctor', required: true) + asciidoctor = find_program('asciidoctor', dirs: program_path) asciidoc_html = 'xhtml5' asciidoc_docbook = 'docbook5' xmlto_extra = [ @@ -283,22 +292,25 @@ elif docs_backend == 'asciidoctor' ] endif -git = find_program('git', required: false) -xmlto = find_program('xmlto') +if get_option('breaking_changes') + asciidoc_common_options += ['--attribute', 'with-breaking-changes'] +endif + +xmlto = find_program('xmlto', dirs: program_path) cmd_lists = [ - 'cmds-ancillaryinterrogators.txt', - 'cmds-ancillarymanipulators.txt', - 'cmds-mainporcelain.txt', - 'cmds-plumbinginterrogators.txt', - 'cmds-plumbingmanipulators.txt', - 'cmds-synchingrepositories.txt', - 'cmds-synchelpers.txt', - 'cmds-guide.txt', - 'cmds-developerinterfaces.txt', - 'cmds-userinterfaces.txt', - 'cmds-purehelpers.txt', - 'cmds-foreignscminterface.txt', + 'cmds-ancillaryinterrogators.adoc', + 'cmds-ancillarymanipulators.adoc', + 'cmds-mainporcelain.adoc', + 'cmds-plumbinginterrogators.adoc', + 'cmds-plumbingmanipulators.adoc', + 'cmds-synchingrepositories.adoc', + 'cmds-synchelpers.adoc', + 'cmds-guide.adoc', + 'cmds-developerinterfaces.adoc', + 'cmds-userinterfaces.adoc', + 'cmds-purehelpers.adoc', + 'cmds-foreignscminterface.adoc', ] documentation_deps += custom_target( @@ -325,7 +337,7 @@ foreach mode : [ 'diff', 'merge' ] 'MERGE_TOOLS_DIR=' + meson.project_source_root() / 'mergetools', ], input: 'generate-mergetool-list.sh', - output: 'mergetools-' + mode + '.txt', + output: 'mergetools-' + mode + '.adoc', ) endforeach @@ -405,7 +417,7 @@ if get_option('docs').contains('html') pointing_to: 'git.html', ) - xsltproc = find_program('xsltproc') + xsltproc = find_program('xsltproc', dirs: program_path) user_manual_xml = custom_target( command: asciidoc_common_options + [ @@ -414,7 +426,7 @@ if get_option('docs').contains('html') '--out-file=@OUTPUT@', '@INPUT@', ], - input: 'user-manual.txt', + input: 'user-manual.adoc', output: 'user-manual.xml', depends: documentation_deps, ) @@ -436,14 +448,14 @@ if get_option('docs').contains('html') ) articles = [ - 'DecisionMaking.txt', - 'MyFirstContribution.txt', - 'MyFirstObjectWalk.txt', - 'ReviewingGuidelines.txt', + 'DecisionMaking.adoc', + 'MyFirstContribution.adoc', + 'MyFirstObjectWalk.adoc', + 'ReviewingGuidelines.adoc', 'SubmittingPatches', - 'ToolsForGit.txt', - 'git-bisect-lk2009.txt', - 'git-tools.txt', + 'ToolsForGit.adoc', + 'git-bisect-lk2009.adoc', + 'git-tools.adoc', ] foreach article : articles @@ -475,8 +487,10 @@ endif # Sanity check that we are not missing any tests present in 't/'. This check # only runs once at configure time and is thus best-effort, only. Furthermore, # it only verifies man pages for the sake of simplicity. -configured_manpages = manpages.keys() + [ 'git-bisect-lk2009.txt', 'git-tools.txt' ] -actual_manpages = run_command(shell, '-c', 'ls git*.txt scalar.txt', +configured_manpages = manpages.keys() +configured_manpages += manpages_breaking_changes.keys() +configured_manpages += [ 'git-bisect-lk2009.adoc', 'git-tools.adoc' ] +actual_manpages = run_command(shell, '-c', 'ls git*.adoc scalar.adoc', check: true, env: script_environment, ).stdout().strip().split('\n') diff --git a/Documentation/object-format-disclaimer.txt b/Documentation/object-format-disclaimer.adoc index e561e6668c..e561e6668c 100644 --- a/Documentation/object-format-disclaimer.txt +++ b/Documentation/object-format-disclaimer.adoc diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.adoc index 8ee940b6a4..07475de8c3 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.adoc @@ -339,10 +339,10 @@ insert an empty string unless we are traversing reflog entries (e.g., by decoration format if `--decorate` was not already provided on the command line. -The boolean options accept an optional value `[=<bool-value>]`. The values -`true`, `false`, `on`, `off` etc. are all accepted. See the "boolean" -sub-section in "EXAMPLES" in linkgit:git-config[1]. If a boolean -option is given with no value, it's enabled. +The boolean options accept an optional value `[=<bool-value>]`. The +values taken by `--type=bool` git-config[1], like `yes` and `off`, +are all accepted. Giving a boolean option without `=<value>` is +equivalent to giving it with `=true`. If you add a `+` (plus sign) after '%' of a placeholder, a line-feed is inserted immediately before the expansion if and only if the diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.adoc index 23888cd612..23888cd612 100644 --- a/Documentation/pretty-options.txt +++ b/Documentation/pretty-options.adoc diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.adoc index d79d2f6065..d79d2f6065 100644 --- a/Documentation/pull-fetch-param.txt +++ b/Documentation/pull-fetch-param.adoc diff --git a/Documentation/ref-reachability-filters.txt b/Documentation/ref-reachability-filters.adoc index 9bae46d84c..9bae46d84c 100644 --- a/Documentation/ref-reachability-filters.txt +++ b/Documentation/ref-reachability-filters.adoc diff --git a/Documentation/ref-storage-format.txt b/Documentation/ref-storage-format.adoc index 14fff8a9c6..14fff8a9c6 100644 --- a/Documentation/ref-storage-format.txt +++ b/Documentation/ref-storage-format.adoc diff --git a/Documentation/rerere-options.txt b/Documentation/rerere-options.adoc index c3321ddea2..c3321ddea2 100644 --- a/Documentation/rerere-options.txt +++ b/Documentation/rerere-options.adoc diff --git a/Documentation/rev-list-description.txt b/Documentation/rev-list-description.adoc index a9efa7fa27..a9efa7fa27 100644 --- a/Documentation/rev-list-description.txt +++ b/Documentation/rev-list-description.adoc diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.adoc index 459e5a02f5..9d020e305a 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.adoc @@ -429,6 +429,7 @@ filtered for `foo`, they look different and equal, respectively.) In the following, we will always refer to the same example history to illustrate the differences between simplification settings. We assume that you are filtering for a file `foo` in this commit graph: + ----------------------------------------------------------------------- .-A---M---N---O---P---Q / / / / / / @@ -436,6 +437,7 @@ that you are filtering for a file `foo` in this commit graph: \ / / / / / `-------------' X ----------------------------------------------------------------------- + The horizontal line of history A---Q is taken to be the first parent of each merge. The commits are: @@ -1024,6 +1026,25 @@ Unexpected missing objects will raise an error. The form '--missing=print' is like 'allow-any', but will also print a list of the missing objects. Object IDs are prefixed with a ``?'' character. + +The form '--missing=print-info' is like 'print', but will also print additional +information about the missing object inferred from its containing object. The +information is all printed on the same line with the missing object ID in the +form: `?<oid> [<token>=<value>]...`. The `<token>=<value>` pairs containing +additional information are separated from each other by a SP. The value is +encoded in a token specific fashion, but SP or LF contained in value are always +expected to be represented in such a way that the resulting encoded value does +not have either of these two problematic bytes. Each `<token>=<value>` may be +one of the following: ++ +-- +* The `path=<path>` shows the path of the missing object inferred from a + containing object. A path containing SP or special characters is enclosed in + double-quotes in the C style as needed. ++ +* The `type=<type>` shows the type of the missing object inferred from a + containing object. +-- ++ If some tips passed to the traversal are missing, they will be considered as missing too, and the traversal will ignore them. In case we cannot get their Object ID though, an error will be raised. @@ -1059,7 +1080,7 @@ more specialized family of commit log tools: linkgit:git-log[1], linkgit:git-show[1], and linkgit:git-whatchanged[1] endif::git-rev-list[] -include::pretty-options.txt[] +include::pretty-options.adoc[] --relative-date:: Synonym for `--date=relative`. diff --git a/Documentation/revisions.txt b/Documentation/revisions.adoc index 6ea6c7cead..6ea6c7cead 100644 --- a/Documentation/revisions.txt +++ b/Documentation/revisions.adoc diff --git a/Documentation/scalar.txt b/Documentation/scalar.adoc index 7e4259c674..7e4259c674 100644 --- a/Documentation/scalar.txt +++ b/Documentation/scalar.adoc diff --git a/Documentation/sequencer.txt b/Documentation/sequencer.adoc index 3bceb56474..3bceb56474 100644 --- a/Documentation/sequencer.txt +++ b/Documentation/sequencer.adoc diff --git a/Documentation/signoff-option.txt b/Documentation/signoff-option.adoc index d98758f3cb..cddfb225d1 100644 --- a/Documentation/signoff-option.txt +++ b/Documentation/signoff-option.adoc @@ -1,8 +1,8 @@ ifdef::git-commit[] --s:: +`-s`:: endif::git-commit[] ---signoff:: ---no-signoff:: +`--signoff`:: +`--no-signoff`:: Add a `Signed-off-by` trailer by the committer at the end of the commit log message. The meaning of a signoff depends on the project to which you're committing. For example, it may certify that @@ -14,5 +14,5 @@ endif::git-commit[] leadership of the project to which you're contributing to understand how the signoffs are used in that project. + -The --no-signoff option can be used to countermand an earlier --signoff +The `--no-signoff` option can be used to countermand an earlier `--signoff` option on the command line. diff --git a/Documentation/technical/.gitignore b/Documentation/technical/.gitignore index 8aa891daee..3caef14a93 100644 --- a/Documentation/technical/.gitignore +++ b/Documentation/technical/.gitignore @@ -1 +1,2 @@ api-index.txt +api-index.adoc diff --git a/Documentation/technical/api-error-handling.txt b/Documentation/technical/api-error-handling.adoc index 665c4960b4..665c4960b4 100644 --- a/Documentation/technical/api-error-handling.txt +++ b/Documentation/technical/api-error-handling.adoc diff --git a/Documentation/technical/api-index-skel.txt b/Documentation/technical/api-index-skel.adoc index 7780a76b08..7780a76b08 100644 --- a/Documentation/technical/api-index-skel.txt +++ b/Documentation/technical/api-index-skel.adoc diff --git a/Documentation/technical/api-index.sh b/Documentation/technical/api-index.sh index 2964885574..dd206b1ca4 100755 --- a/Documentation/technical/api-index.sh +++ b/Documentation/technical/api-index.sh @@ -13,18 +13,18 @@ OUTPUT="$2" cd "$SOURCE_DIR" c=//////////////////////////////////////////////////////////////// - skel=api-index-skel.txt + skel=api-index-skel.adoc sed -e '/^\/\/ table of contents begin/q' "$skel" echo "$c" - ls api-*.txt | + ls api-*.adoc | while read filename do case "$filename" in - api-index-skel.txt | api-index.txt) continue ;; + api-index-skel.adoc | api-index.adoc) continue ;; esac title=$(sed -e 1q "$filename") - html=${filename%.txt}.html + html=${filename%.adoc}.html echo "* link:$html[$title]" done echo "$c" diff --git a/Documentation/technical/api-merge.txt b/Documentation/technical/api-merge.adoc index c2ba01828c..c2ba01828c 100644 --- a/Documentation/technical/api-merge.txt +++ b/Documentation/technical/api-merge.adoc diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.adoc index 61fa6ee167..61fa6ee167 100644 --- a/Documentation/technical/api-parse-options.txt +++ b/Documentation/technical/api-parse-options.adoc diff --git a/Documentation/technical/api-path-walk.adoc b/Documentation/technical/api-path-walk.adoc new file mode 100644 index 0000000000..3e089211fb --- /dev/null +++ b/Documentation/technical/api-path-walk.adoc @@ -0,0 +1,72 @@ +Path-Walk API +============= + +The path-walk API is used to walk reachable objects, but to visit objects +in batches based on a common path they appear in, or by type. + +For example, all reachable commits are visited in a group. All tags are +visited in a group. Then, all root trees are visited. At some point, all +blobs reachable via a path `my/dir/to/A` are visited. When there are +multiple paths possible to reach the same object, then only one of those +paths is used to visit the object. + +Basics +------ + +To use the path-walk API, include `path-walk.h` and call +`walk_objects_by_path()` with a customized `path_walk_info` struct. The +struct is used to set all of the options for how the walk should proceed. +Let's dig into the different options and their use. + +`path_fn` and `path_fn_data`:: + The most important option is the `path_fn` option, which is a + function pointer to the callback that can execute logic on the + object IDs for objects grouped by type and path. This function + also receives a `data` value that corresponds to the + `path_fn_data` member, for providing custom data structures to + this callback function. + +`revs`:: + To configure the exact details of the reachable set of objects, + use the `revs` member and initialize it using the revision + machinery in `revision.h`. Initialize `revs` using calls such as + `setup_revisions()` or `parse_revision_opt()`. Do not call + `prepare_revision_walk()`, as that will be called within + `walk_objects_by_path()`. ++ +It is also important that you do not specify the `--objects` flag for the +`revs` struct. The revision walk should only be used to walk commits, and +the objects will be walked in a separate way based on those starting +commits. + +`commits`, `blobs`, `trees`, `tags`:: + By default, these members are enabled and signal that the path-walk + API should call the `path_fn` on objects of these types. Specialized + applications could disable some options to make it simpler to walk + the objects or to have fewer calls to `path_fn`. ++ +While it is possible to walk only commits in this way, consumers would be +better off using the revision walk API instead. + +`prune_all_uninteresting`:: + By default, all reachable paths are emitted by the path-walk API. + This option allows consumers to declare that they are not + interested in paths where all included objects are marked with the + `UNINTERESTING` flag. This requires using the `boundary` option in + the revision walk so that the walk emits commits marked with the + `UNINTERESTING` flag. + +`pl`:: + This pattern list pointer allows focusing the path-walk search to + a set of patterns, only emitting paths that match the given + patterns. See linkgit:gitignore[5] or + linkgit:git-sparse-checkout[1] for details about pattern lists. + When the pattern list uses cone-mode patterns, then the path-walk + API can prune the set of paths it walks to improve performance. + +Examples +-------- + +See example usages in: + `t/helper/test-path-walk.c`, + `builtin/backfill.c` diff --git a/Documentation/technical/api-simple-ipc.txt b/Documentation/technical/api-simple-ipc.adoc index c4fb152b23..972178b042 100644 --- a/Documentation/technical/api-simple-ipc.txt +++ b/Documentation/technical/api-simple-ipc.adoc @@ -36,7 +36,7 @@ Comparison with sub-process model --------------------------------- The Simple-IPC mechanism differs from the existing `sub-process.c` -model (Documentation/technical/long-running-process-protocol.txt) and +model (Documentation/technical/long-running-process-protocol.adoc) and used by applications like Git-LFS. In the LFS-style sub-process model, the helper is started by the foreground process, communication happens via a pair of file descriptors bound to the stdin/stdout of the diff --git a/Documentation/technical/api-trace2.txt b/Documentation/technical/api-trace2.adoc index 5817b18310..cf493dae03 100644 --- a/Documentation/technical/api-trace2.txt +++ b/Documentation/technical/api-trace2.adoc @@ -140,7 +140,7 @@ $ cat ~/log.event To enable a target, set the corresponding environment variable or system or global config value to one of the following: -include::../trace2-target-values.txt[] +include::../trace2-target-values.adoc[] When trace files are written to a target directory, they will be named according to the last component of the SID (optionally followed by a counter to avoid diff --git a/Documentation/technical/bitmap-format.txt b/Documentation/technical/bitmap-format.adoc index bfb0ec7beb..bfb0ec7beb 100644 --- a/Documentation/technical/bitmap-format.txt +++ b/Documentation/technical/bitmap-format.adoc diff --git a/Documentation/technical/build-systems.txt b/Documentation/technical/build-systems.adoc index d9dafb407c..d9dafb407c 100644 --- a/Documentation/technical/build-systems.txt +++ b/Documentation/technical/build-systems.adoc diff --git a/Documentation/technical/bundle-uri.txt b/Documentation/technical/bundle-uri.adoc index 91d3a13e32..91d3a13e32 100644 --- a/Documentation/technical/bundle-uri.txt +++ b/Documentation/technical/bundle-uri.adoc diff --git a/Documentation/technical/commit-graph.txt b/Documentation/technical/commit-graph.adoc index 2c26e95e51..2c26e95e51 100644 --- a/Documentation/technical/commit-graph.txt +++ b/Documentation/technical/commit-graph.adoc diff --git a/Documentation/technical/directory-rename-detection.txt b/Documentation/technical/directory-rename-detection.adoc index 029ee2cedc..029ee2cedc 100644 --- a/Documentation/technical/directory-rename-detection.txt +++ b/Documentation/technical/directory-rename-detection.adoc diff --git a/Documentation/technical/hash-function-transition.txt b/Documentation/technical/hash-function-transition.adoc index 7102c7c8f5..f047fd80ca 100644 --- a/Documentation/technical/hash-function-transition.txt +++ b/Documentation/technical/hash-function-transition.adoc @@ -394,7 +394,7 @@ inflated again in step 3, for a total of two inflations. Step 4 is probably necessary for good read-time performance. "git pack-objects" on the server optimizes the pack file for good data -locality (see Documentation/technical/pack-heuristics.txt). +locality (see Documentation/technical/pack-heuristics.adoc). Details of this process are likely to change. It will take some experimenting to get this to perform well. diff --git a/Documentation/technical/large-object-promisors.adoc b/Documentation/technical/large-object-promisors.adoc new file mode 100644 index 0000000000..dea8dafa66 --- /dev/null +++ b/Documentation/technical/large-object-promisors.adoc @@ -0,0 +1,656 @@ +Large Object Promisors +====================== + +Since Git has been created, users have been complaining about issues +with storing large files in Git. Some solutions have been created to +help, but they haven't helped much with some issues. + +Git currently supports multiple promisor remotes, which could help +with some of these remaining issues, but it's very hard to use them to +help, because a number of important features are missing. + +The goal of the effort described in this document is to add these +important features. + +We will call a "Large Object Promisor", or "LOP" in short, a promisor +remote which is used to store only large blobs and which is separate +from the main remote that should store the other Git objects and the +rest of the repos. + +By extension, we will also call "Large Object Promisor", or LOP, the +effort described in this document to add a set of features to make it +easier to handle large blobs/files in Git by using LOPs. + +This effort aims to especially improve things on the server side, and +especially for large blobs that are already compressed in a binary +format. + +This effort aims to provide an alternative to Git LFS +(https://git-lfs.com/) and similar tools like git-annex +(https://git-annex.branchable.com/) for handling large files, even +though a complete alternative would very likely require other efforts +especially on the client side, where it would likely help to implement +a new object representation for large blobs as discussed in: + +https://lore.kernel.org/git/xmqqbkdometi.fsf@gitster.g/ + +0) Non goals +------------ + +- We will not discuss those client side improvements here, as they + would require changes in different parts of Git than this effort. ++ +So we don't pretend to fully replace Git LFS with only this effort, +but we nevertheless believe that it can significantly improve the +current situation on the server side, and that other separate +efforts could also improve the situation on the client side. + +- In the same way, we are not going to discuss all the possible ways + to implement a LOP or their underlying object storage, or to + optimize how LOP works. ++ +Our opinion is that the simplest solution for now is for LOPs to use +object storage through a remote helper (see section II.2 below for +more details) to store their objects. So we consider that this is the +default implementation. If there are improvements on top of this, +that's great, but our opinion is that such improvements are not +necessary for LOPs to already be useful. Such improvements are likely +a different technical topic, and can be taken care of separately +anyway. ++ +So in particular we are not going to discuss pluggable ODBs or other +object database backends that could chunk large blobs, dedup the +chunks and store them efficiently. Sure, that would be a nice +improvement to store large blobs on the server side, but we believe +it can just be a separate effort as it's also not technically very +related to this effort. ++ +We are also not going to discuss data transfer improvements between +LOPs and clients or servers. Sure, there might be some easy and very +effective optimizations there (as we know that objects on LOPs are +very likely incompressible and not deltifying well), but this can be +dealt with separately in a separate effort. + +In other words, the goal of this document is not to talk about all the +possible ways to optimize how Git could handle large blobs, but to +describe how a LOP based solution can already work well and alleviate +a number of current issues in the context of Git clients and servers +sharing Git objects. + +Even if LOPs are used not very efficiently, they can still be useful +and worth using in some cases, as we will see in more details +later in this document: + + - they can make it simpler for clients to use promisor remotes and + therefore avoid fetching a lot of large blobs they might not need + locally, + + - they can make it significantly cheaper or easier for servers to + host a significant part of the current repository content, and + even more to host content with larger blobs or more large blobs + than currently. + +I) Issues with the current situation +------------------------------------ + +- Some statistics made on GitLab repos have shown that more than 75% + of the disk space is used by blobs that are larger than 1MB and + often in a binary format. + +- So even if users could use Git LFS or similar tools to store a lot + of large blobs out of their repos, it's a fact that in practice they + don't do it as much as they probably should. + +- On the server side ideally, the server should be able to decide for + itself how it stores things. It should not depend on users deciding + to use tools like Git LFS on some blobs or not. + +- It's much more expensive to store large blobs that don't delta + compress well on regular fast seeking drives (like SSDs) than on + object storage (like Amazon S3 or GCP Buckets). Using fast drives + for regular Git repos makes sense though, as serving regular Git + content (blobs containing text or code) needs drives where seeking + is fast, but the content is relatively small. On the other hand, + object storage for Git LFS blobs makes sense as seeking speed is not + as important when dealing with large files, while costs are more + important. So the fact that users don't use Git LFS or similar tools + for a significant number of large blobs has likely some bad + consequences on the cost of repo storage for most Git hosting + platforms. + +- Having large blobs handled in the same way as other blobs and Git + objects in Git repos instead of on object storage also has a cost in + increased memory and CPU usage, and therefore decreased performance, + when creating packfiles. (This is because Git tries to use delta + compression or zlib compression which is unlikely to work well on + already compressed binary content.) So it's not just a storage cost + increase. + +- When a large blob has been committed into a repo, it might not be + possible to remove this blob from the repo without rewriting + history, even if the user then decides to use Git LFS or a similar + tool to handle it. + +- In fact Git LFS and similar tools are not very flexible in letting + users change their minds about the blobs they should handle or not. + +- Even when users are using Git LFS or similar tools, they are often + complaining that these tools require significant effort to set up, + learn and use correctly. + +II) Main features of the "Large Object Promisors" solution +---------------------------------------------------------- + +The main features below should give a rough overview of how the +solution may work. Details about needed elements can be found in +following sections. + +Even if each feature below is very useful for the full solution, it is +very likely to be also useful on its own in some cases where the full +solution is not required. However, we'll focus primarily on the big +picture here. + +Also each feature doesn't need to be implemented entirely in Git +itself. Some could be scripts, hooks or helpers that are not part of +the Git repo. It would be helpful if those could be shared and +improved on collaboratively though. So we want to encourage sharing +them. + +1) Large blobs are stored on LOPs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Large blobs should be stored on special promisor remotes that we will +call "Large Object Promisors" or LOPs. These LOPs should be additional +remotes dedicated to contain large blobs especially those in binary +format. They should be used along with main remotes that contain the +other objects. + +Note 1 +++++++ + +To clarify, a LOP is a normal promisor remote, except that: + +- it should store only large blobs, + +- it should be separate from the main remote, so that the main remote + can focus on serving other objects and the rest of the repos (see + feature 4) below) and can use the LOP as a promisor remote for + itself. + +Note 2 +++++++ + +Git already makes it possible for a main remote to also be a promisor +remote storing both regular objects and large blobs for a client that +clones from it with a filter on blob size. But here we explicitly want +to avoid that. + +Rationale ++++++++++ + +LOPs aim to be good at handling large blobs while main remotes are +already good at handling other objects. + +Implementation +++++++++++++++ + +Git already has support for multiple promisor remotes, see +link:partial-clone.html#using-many-promisor-remotes[the partial clone documentation]. + +Also, Git already has support for partial clone using a filter on the +size of the blobs (with `git clone --filter=blob:limit=<size>`). Most +of the other main features below are based on these existing features +and are about making them easy and efficient to use for the purpose of +better handling large blobs. + +2) LOPs can use object storage +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +LOPs can be implemented using object storage, like an Amazon S3 or GCP +Bucket or MinIO (which is open source under the GNU AGPLv3 license) to +actually store the large blobs, and can be accessed through a Git +remote helper (see linkgit:gitremote-helpers[7]) which makes the +underlying object storage appear like a remote to Git. + +Note +++++ + +A LOP can be a promisor remote accessed using a remote helper by +both some clients and the main remote. + +Rationale ++++++++++ + +This looks like the simplest way to create LOPs that can cheaply +handle many large blobs. + +Implementation +++++++++++++++ + +Remote helpers are quite easy to write as shell scripts, but it might +be more efficient and maintainable to write them using other languages +like Go. + +Some already exist under open source licenses, for example: + + - https://github.com/awslabs/git-remote-s3 + - https://gitlab.com/eric.p.ju/git-remote-gs + +Other ways to implement LOPs are certainly possible, but the goal of +this document is not to discuss how to best implement a LOP or its +underlying object storage (see the "0) Non goals" section above). + +3) LOP object storage can be Git LFS storage +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The underlying object storage that a LOP uses could also serve as +storage for large files handled by Git LFS. + +Rationale ++++++++++ + +This would simplify the server side if it wants to both use a LOP and +act as a Git LFS server. + +4) A main remote can offload to a LOP with a configurable threshold +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +On the server side, a main remote should have a way to offload to a +LOP all its blobs with a size over a configurable threshold. + +Rationale ++++++++++ + +This makes it easy to set things up and to clean things up. For +example, an admin could use this to manually convert a repo not using +LOPs to a repo using a LOP. On a repo already using a LOP but where +some users would sometimes push large blobs, a cron job could use this +to regularly make sure the large blobs are moved to the LOP. + +Implementation +++++++++++++++ + +Using something based on `git repack --filter=...` to separate the +blobs we want to offload from the other Git objects could be a good +idea. The missing part is to connect to the LOP, check if the blobs we +want to offload are already there and if not send them. + +5) A main remote should try to remain clean from large blobs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A main remote should try to avoid containing a lot of oversize +blobs. For that purpose, it should offload as needed to a LOP and it +should have ways to prevent oversize blobs to be fetched, and also +perhaps pushed, into it. + +Rationale ++++++++++ + +A main remote containing many oversize blobs would defeat the purpose +of LOPs. + +Implementation +++++++++++++++ + +The way to offload to a LOP discussed in 4) above can be used to +regularly offload oversize blobs. About preventing oversize blobs from +being fetched into the repo see 6) below. About preventing oversize +blob pushes, a pre-receive hook could be used. + +Also there are different scenarios in which large blobs could get +fetched into the main remote, for example: + +- A client that doesn't implement the "promisor-remote" protocol + (described in 6) below) clones from the main remote. + +- The main remote gets a request for information about a large blob + and is not able to get that information without fetching the blob + from the LOP. + +It might not be possible to completely prevent all these scenarios +from happening. So the goal here should be to implement features that +make the fetching of large blobs less likely. For example adding a +`remote-object-info` command in the `git cat-file --batch` protocol +and its variants might make it possible for a main repo to respond to +some requests about large blobs without fetching them. + +6) A protocol negotiation should happen when a client clones +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When a client clones from a main repo, there should be a protocol +negotiation so that the server can advertise one or more LOPs and so +that the client and the server can discuss if the client could +directly use a LOP the server is advertising. If the client and the +server can agree on that, then the client would be able to get the +large blobs directly from the LOP and the server would not need to +fetch those blobs from the LOP to be able to serve the client. + +Note +++++ + +For fetches instead of clones, a protocol negotiation might not always +happen, see the "What about fetches?" FAQ entry below for details. + +Rationale ++++++++++ + +Security, configurability and efficiency of setting things up. + +Implementation +++++++++++++++ + +A "promisor-remote" protocol v2 capability looks like a good way to +implement this. The way the client and server use this capability +could be controlled by configuration variables. + +Information that the server could send to the client through that +protocol could be things like: LOP name, LOP URL, filter-spec (for +example `blob:limit=<size>`) or just size limit that should be used as +a filter when cloning, token to be used with the LOP, etc. + +7) A client can offload to a LOP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When a client is using a LOP that is also a LOP of its main remote, +the client should be able to offload some large blobs it has fetched, +but might not need anymore, to the LOP. + +Note +++++ + +It might depend on the context if it should be OK or not for clients +to offload large blobs they have created, instead of fetched, directly +to the LOP without the main remote checking them in some ways +(possibly using hooks or other tools). + +This should be discussed and refined when we get closer to +implementing this feature. + +Rationale ++++++++++ + +On the client, the easiest way to deal with unneeded large blobs is to +offload them. + +Implementation +++++++++++++++ + +This is very similar to what 4) above is about, except on the client +side instead of the server side. So a good solution to 4) could likely +be adapted to work on the client side too. + +There might be some security issues here, as there is no negotiation, +but they might be mitigated if the client can reuse a token it got +when cloning (see 6) above). Also if the large blobs were fetched from +a LOP, it is likely, and can easily be confirmed, that the LOP still +has them, so that they can just be removed from the client. + +III) Benefits of using LOPs +--------------------------- + +Many benefits are related to the issues discussed in "I) Issues with +the current situation" above: + +- No need to rewrite history when deciding which blobs are worth + handling separately than other objects, or when moving or removing + the threshold. + +- If the protocol between client and server is developed and secured + enough, then many details might be setup on the server side only and + all the clients could then easily get all the configuration + information and use it to set themselves up mostly automatically. + +- Storage costs benefits on the server side. + +- Reduced memory and CPU needs on main remotes on the server side. + +- Reduced storage needs on the client side. + +IV) FAQ +------- + +What about using multiple LOPs on the server and client side? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +That could perhaps be useful in some cases, but for now it's more +likely that in most cases a single LOP will be advertised by the +server and should be used by the client. + +A case where it could be useful for a server to advertise multiple +LOPs is if a LOP is better for some users while a different LOP is +better for other users. For example some clients might have a better +connection to a LOP than others. + +In those cases it's the responsibility of the server to have some +documentation to help clients. It could say for example something like +"Users in this part of the world might want to pick only LOP A as it +is likely to be better connected to them, while users in other parts +of the world should pick only LOP B for the same reason." + +When should we trust or not trust the LOPs advertised by the server? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In some contexts, like in corporate setup where the server and all the +clients are parts of an internal network in a company where admins +have all the rights on every system, it's OK, and perhaps even a good +thing, if the clients fully trust the server, as it can help ensure +that all the clients are on the same page. + +There are also contexts in which clients trust a code hosting platform +serving them some repos, but might not fully trust other users +managing or contributing to some of these repos. For example, the code +hosting platform could have hooks in place to check that any object it +receives doesn't contain malware or otherwise bad content. In this +case it might be OK for the client to use a main remote and its LOP if +they are both hosted by the code hosting platform, but not if the LOP +is hosted elsewhere (where the content is not checked). + +In other contexts, a client should just not trust a server. + +So there should be different ways to configure how the client should +behave when a server advertises a LOP to it at clone time. + +As the basic elements that a server can advertise about a LOP are a +LOP name and a LOP URL, the client should base its decision about +accepting a LOP on these elements. + +One simple way to be very strict in the LOP it accepts is for example +for the client to check that the LOP is already configured on the +client with the same name and URL as what the server advertises. + +In general default and "safe" settings should require that the LOP are +configured on the client separately from the "promisor-remote" +protocol and that the client accepts a LOP only when information about +it from the protocol matches what has been already configured +separately. + +What about LOP names? +~~~~~~~~~~~~~~~~~~~~~ + +In some contexts, for example if the clients sometimes fetch from each +other, it can be a good idea for all the clients to use the same names +for all the remotes they use, including LOPs. + +In other contexts, each client might want to be able to give the name +it wants to each remote, including each LOP, it interacts with. + +So there should be different ways to configure how the client accepts +or not the LOP name the server advertises. + +If a default or "safe" setting is used, then as such a setting should +require that the LOP be configured separately, then the name would be +configured separately and there is no risk that the server could +dictate a name to a client. + +Could the main remote be bogged down by old or paranoid clients? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Yes, it could happen if there are too many clients that are either +unwilling to trust the main remote or that just don't implement the +"promisor-remote" protocol because they are too old or not fully +compatible with the 'git' client. + +When serving such a client, the main remote has no other choice than +to first fetch from its LOP, to then be able to provide to the client +everything it requested. So the main remote, even if it has cleanup +mechanisms (see section II.4 above), would be burdened at least +temporarily with the large blobs it had to fetch from its LOP. + +Not behaving like this would be breaking backward compatibility, and +could be seen as segregating clients. For example, it might be +possible to implement a special mode that allows the server to just +reject clients that don't implement the "promisor-remote" protocol or +aren't willing to trust the main remote. This mode might be useful in +a special context like a corporate environment. There is no plan to +implement such a mode though, and this should be discussed separately +later anyway. + +A better way to proceed is probably for the main remote to show a +message telling clients that don't implement the protocol or are +unwilling to accept the advertised LOP(s) that they would get faster +clone and fetches by upgrading client software or properly setting +them up to accept LOP(s). + +Waiting for clients to upgrade, monitoring these upgrades and limiting +the use of LOPs to repos that are not very frequently accessed might +be other good ways to make sure that some benefits are still reaped +from LOPs. Over time, as more and more clients upgrade and benefit +from LOPs, using them in more and more frequently accessed repos will +become worth it. + +Corporate environments, where it might be easier to make sure that all +the clients are up-to-date and properly configured, could hopefully +benefit more and earlier from using LOPs. + +What about fetches? +~~~~~~~~~~~~~~~~~~~ + +There are different kinds of fetches. A regular fetch happens when +some refs have been updated on the server and the client wants the ref +updates and possibly the new objects added with them. A "backfill" or +"lazy" fetch, on the contrary, happens when the client needs to use +some objects it already knows about but doesn't have because they are +on a promisor remote. + +Regular fetch ++++++++++++++ + +In a regular fetch, the client will contact the main remote and a +protocol negotiation will happen between them. It's a good thing that +a protocol negotiation happens every time, as the configuration on the +client or the main remote could have changed since the previous +protocol negotiation. In this case, the new protocol negotiation +should ensure that the new fetch will happen in a way that satisfies +the new configuration of both the client and the server. + +In most cases though, the configurations on the client and the main +remote will not have changed between 2 fetches or between the initial +clone and a subsequent fetch. This means that the result of a new +protocol negotiation will be the same as the previous result, so the +new fetch will happen in the same way as the previous clone or fetch, +using, or not using, the same LOP(s) as last time. + +"Backfill" or "lazy" fetch +++++++++++++++++++++++++++ + +When there is a backfill fetch, the client doesn't necessarily contact +the main remote first. It will try to fetch from its promisor remotes +in the order they appear in the config file, except that a remote +configured using the `extensions.partialClone` config variable will be +tried last. See +link:partial-clone.html#using-many-promisor-remotes[the partial clone documentation]. + +This is not new with this effort. In fact this is how multiple remotes +have already been working for around 5 years. + +When using LOPs, having the main remote configured using +`extensions.partialClone`, so it's tried last, makes sense, as missing +objects should only be large blobs that are on LOPs. + +This means that a protocol negotiation will likely not happen as the +missing objects will be fetched from the LOPs, and then there will be +nothing left to fetch from the main remote. + +To secure that, it could be a good idea for LOPs to require a token +from the client when it fetches from them. The client could get the +token when performing a protocol negotiation with the main remote (see +section II.6 above). + +V) Future improvements +---------------------- + +It is expected that at the beginning using LOPs will be mostly worth +it either in a corporate context where the Git version that clients +use can easily be controlled, or on repos that are infrequently +accessed. (See the "Could the main remote be bogged down by old or +paranoid clients?" section in the FAQ above.) + +Over time, as more and more clients upgrade to a version that +implements the "promisor-remote" protocol v2 capability described +above in section II.6), it will be worth it to use LOPs more widely. + +A lot of improvements may also help using LOPs more widely. Some of +these improvements are part of the scope of this document like the +following: + + - Implementing a "remote-object-info" command in the + `git cat-file --batch` protocol and its variants to allow main + remotes to respond to requests about large blobs without fetching + them. (Eric Ju has started working on this based on previous work + by Calvin Wan.) + + - Creating better cleanup and offload mechanisms for main remotes + and clients to prevent accumulation of large blobs. + + - Developing more sophisticated protocol negotiation capabilities + between clients and servers for handling LOPs, for example adding + a filter-spec (e.g., blob:limit=<size>) or size limit for + filtering when cloning, or adding a token for LOP authentication. + + - Improving security measures for LOP access, particularly around + token handling and authentication. + + - Developing standardized ways to configure and manage multiple LOPs + across different environments. Especially in the case where + different LOPs serve the same content to clients in different + geographical locations, there is a need for replication or + synchronization between LOPs. + +Some improvements, including some that have been mentioned in the "0) +Non Goals" section of this document, are out of the scope of this +document: + + - Implementing a new object representation for large blobs on the + client side. + + - Developing pluggable ODBs or other object database backends that + could chunk large blobs, dedup the chunks and store them + efficiently. + + - Optimizing data transfer between LOPs and clients/servers, + particularly for incompressible and non-deltifying content. + + - Creating improved client side tools for managing large objects + more effectively, for example tools for migrating from Git LFS or + git-annex, or tools to find which objects could be offloaded and + how much disk space could be reclaimed by offloading them. + +Some improvements could be seen as part of the scope of this document, +but might already have their own separate projects from the Git +project, like: + + - Improving existing remote helpers to access object storage or + developing new ones. + + - Improving existing object storage solutions or developing new + ones. + +Even though all the above improvements may help, this document and the +LOP effort should try to focus, at least first, on a relatively small +number of improvements mostly those that are in its current scope. + +For example introducing pluggable ODBs and a new object database +backend is likely a multi-year effort on its own that can happen +separately in parallel. It has different technical requirements, +touches other part of the Git code base and should have its own design +document(s). diff --git a/Documentation/technical/long-running-process-protocol.txt b/Documentation/technical/long-running-process-protocol.adoc index 6f33654b42..6f33654b42 100644 --- a/Documentation/technical/long-running-process-protocol.txt +++ b/Documentation/technical/long-running-process-protocol.adoc diff --git a/Documentation/technical/meson.build b/Documentation/technical/meson.build index 21dfb8b5c9..a13aafcfbb 100644 --- a/Documentation/technical/meson.build +++ b/Documentation/technical/meson.build @@ -1,37 +1,37 @@ api_docs = [ - 'api-error-handling.txt', - 'api-merge.txt', - 'api-parse-options.txt', - 'api-simple-ipc.txt', - 'api-trace2.txt', + 'api-error-handling.adoc', + 'api-merge.adoc', + 'api-parse-options.adoc', + 'api-simple-ipc.adoc', + 'api-trace2.adoc', ] articles = [ - 'bitmap-format.txt', - 'build-systems.txt', - 'bundle-uri.txt', - 'commit-graph.txt', - 'directory-rename-detection.txt', - 'hash-function-transition.txt', - 'long-running-process-protocol.txt', - 'multi-pack-index.txt', - 'packfile-uri.txt', - 'pack-heuristics.txt', - 'parallel-checkout.txt', - 'partial-clone.txt', - 'platform-support.txt', - 'racy-git.txt', - 'reftable.txt', - 'remembering-renames.txt', - 'repository-version.txt', - 'rerere.txt', - 'scalar.txt', - 'send-pack-pipeline.txt', - 'shallow.txt', - 'sparse-checkout.txt', - 'sparse-index.txt', - 'trivial-merge.txt', - 'unit-tests.txt', + 'bitmap-format.adoc', + 'build-systems.adoc', + 'bundle-uri.adoc', + 'commit-graph.adoc', + 'directory-rename-detection.adoc', + 'hash-function-transition.adoc', + 'long-running-process-protocol.adoc', + 'multi-pack-index.adoc', + 'packfile-uri.adoc', + 'pack-heuristics.adoc', + 'parallel-checkout.adoc', + 'partial-clone.adoc', + 'platform-support.adoc', + 'racy-git.adoc', + 'reftable.adoc', + 'remembering-renames.adoc', + 'repository-version.adoc', + 'rerere.adoc', + 'scalar.adoc', + 'send-pack-pipeline.adoc', + 'shallow.adoc', + 'sparse-checkout.adoc', + 'sparse-index.adoc', + 'trivial-merge.adoc', + 'unit-tests.adoc', ] api_index = custom_target( @@ -43,7 +43,7 @@ api_index = custom_target( ], env: script_environment, input: api_docs, - output: 'api-index.txt', + output: 'api-index.adoc', ) custom_target( @@ -60,6 +60,7 @@ foreach article : api_docs + articles command: asciidoc_html_options, input: article, output: fs.stem(article) + '.html', + depends: documentation_deps, install: true, install_dir: get_option('datadir') / 'doc/git-doc/technical', ) diff --git a/Documentation/technical/multi-pack-index.txt b/Documentation/technical/multi-pack-index.adoc index cc063b30be..cc063b30be 100644 --- a/Documentation/technical/multi-pack-index.txt +++ b/Documentation/technical/multi-pack-index.adoc diff --git a/Documentation/technical/pack-heuristics.txt b/Documentation/technical/pack-heuristics.adoc index 95a07db6e8..95a07db6e8 100644 --- a/Documentation/technical/pack-heuristics.txt +++ b/Documentation/technical/pack-heuristics.adoc diff --git a/Documentation/technical/packfile-uri.txt b/Documentation/technical/packfile-uri.adoc index 9d453d4765..9d453d4765 100644 --- a/Documentation/technical/packfile-uri.txt +++ b/Documentation/technical/packfile-uri.adoc diff --git a/Documentation/technical/parallel-checkout.txt b/Documentation/technical/parallel-checkout.adoc index b4a144e5f4..b4a144e5f4 100644 --- a/Documentation/technical/parallel-checkout.txt +++ b/Documentation/technical/parallel-checkout.adoc diff --git a/Documentation/technical/partial-clone.txt b/Documentation/technical/partial-clone.adoc index bf5ec5c82d..e513e391ea 100644 --- a/Documentation/technical/partial-clone.txt +++ b/Documentation/technical/partial-clone.adoc @@ -85,7 +85,7 @@ See "filter" in linkgit:gitprotocol-pack[5]. server to request filtering during packfile construction. + There are various filters available to accommodate different situations. -See "--filter=<filter-spec>" in Documentation/rev-list-options.txt. +See "--filter=<filter-spec>" in Documentation/rev-list-options.adoc. - On the server pack-objects applies the requested filter-spec as it creates "filtered" packfiles for the client. diff --git a/Documentation/technical/platform-support.txt b/Documentation/technical/platform-support.adoc index 0a2fb28d62..0a2fb28d62 100644 --- a/Documentation/technical/platform-support.txt +++ b/Documentation/technical/platform-support.adoc diff --git a/Documentation/technical/racy-git.txt b/Documentation/technical/racy-git.adoc index 59bea66c0f..59bea66c0f 100644 --- a/Documentation/technical/racy-git.txt +++ b/Documentation/technical/racy-git.adoc diff --git a/Documentation/technical/reftable.txt b/Documentation/technical/reftable.adoc index dd0b37c4e3..dd0b37c4e3 100644 --- a/Documentation/technical/reftable.txt +++ b/Documentation/technical/reftable.adoc diff --git a/Documentation/technical/remembering-renames.txt b/Documentation/technical/remembering-renames.adoc index 73f41761e2..73f41761e2 100644 --- a/Documentation/technical/remembering-renames.txt +++ b/Documentation/technical/remembering-renames.adoc diff --git a/Documentation/technical/repository-version.txt b/Documentation/technical/repository-version.adoc index b9bb81a81f..b9bb81a81f 100644 --- a/Documentation/technical/repository-version.txt +++ b/Documentation/technical/repository-version.adoc diff --git a/Documentation/technical/rerere.txt b/Documentation/technical/rerere.adoc index 580f23360a..580f23360a 100644 --- a/Documentation/technical/rerere.txt +++ b/Documentation/technical/rerere.adoc diff --git a/Documentation/technical/scalar.txt b/Documentation/technical/scalar.adoc index 921cb104c3..921cb104c3 100644 --- a/Documentation/technical/scalar.txt +++ b/Documentation/technical/scalar.adoc diff --git a/Documentation/technical/send-pack-pipeline.txt b/Documentation/technical/send-pack-pipeline.adoc index 9b5a0bc186..9b5a0bc186 100644 --- a/Documentation/technical/send-pack-pipeline.txt +++ b/Documentation/technical/send-pack-pipeline.adoc diff --git a/Documentation/technical/shallow.txt b/Documentation/technical/shallow.adoc index f3738baa0f..f3738baa0f 100644 --- a/Documentation/technical/shallow.txt +++ b/Documentation/technical/shallow.adoc diff --git a/Documentation/technical/sparse-checkout.txt b/Documentation/technical/sparse-checkout.adoc index d968659354..d968659354 100644 --- a/Documentation/technical/sparse-checkout.txt +++ b/Documentation/technical/sparse-checkout.adoc diff --git a/Documentation/technical/sparse-index.txt b/Documentation/technical/sparse-index.adoc index 3b24c1a219..3b24c1a219 100644 --- a/Documentation/technical/sparse-index.txt +++ b/Documentation/technical/sparse-index.adoc diff --git a/Documentation/technical/trivial-merge.txt b/Documentation/technical/trivial-merge.adoc index 1f1c33d0da..1f1c33d0da 100644 --- a/Documentation/technical/trivial-merge.txt +++ b/Documentation/technical/trivial-merge.adoc diff --git a/Documentation/technical/unit-tests.txt b/Documentation/technical/unit-tests.adoc index 5a432b7b29..5a432b7b29 100644 --- a/Documentation/technical/unit-tests.txt +++ b/Documentation/technical/unit-tests.adoc diff --git a/Documentation/trace2-target-values.txt b/Documentation/trace2-target-values.adoc index 06f1953313..06f1953313 100644 --- a/Documentation/trace2-target-values.txt +++ b/Documentation/trace2-target-values.adoc diff --git a/Documentation/transfer-data-leaks.txt b/Documentation/transfer-data-leaks.adoc index 914bacc39e..914bacc39e 100644 --- a/Documentation/transfer-data-leaks.txt +++ b/Documentation/transfer-data-leaks.adoc diff --git a/Documentation/urls-remotes.txt b/Documentation/urls-remotes.adoc index bf17012241..9b10151198 100644 --- a/Documentation/urls-remotes.txt +++ b/Documentation/urls-remotes.adoc @@ -1,4 +1,4 @@ -include::urls.txt[] +include::urls.adoc[] REMOTES[[REMOTES]] ------------------ diff --git a/Documentation/urls.txt b/Documentation/urls.adoc index 9c871e716a..9c871e716a 100644 --- a/Documentation/urls.txt +++ b/Documentation/urls.adoc diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.adoc index 90a4189358..d2b478ad23 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.adoc @@ -4354,7 +4354,7 @@ itself! [[git-explained]] === Git explained -include::glossary-content.txt[] +include::glossary-content.adoc[] [[git-quick-start]] [appendix] diff --git a/GIT-BUILD-OPTIONS.in b/GIT-BUILD-OPTIONS.in index edff75ae16..0a9884e0ad 100644 --- a/GIT-BUILD-OPTIONS.in +++ b/GIT-BUILD-OPTIONS.in @@ -9,14 +9,13 @@ GIT_PERF_MAKE_COMMAND=@GIT_PERF_MAKE_COMMAND@ GIT_PERF_MAKE_OPTS=@GIT_PERF_MAKE_OPTS@ GIT_PERF_REPEAT_COUNT=@GIT_PERF_REPEAT_COUNT@ GIT_PERF_REPO=@GIT_PERF_REPO@ +GIT_SOURCE_DIR=@GIT_SOURCE_DIR@ GIT_TEST_CMP=@GIT_TEST_CMP@ GIT_TEST_CMP_USE_COPIED_CONTEXT=@GIT_TEST_CMP_USE_COPIED_CONTEXT@ GIT_TEST_GITPERLLIB=@GIT_TEST_GITPERLLIB@ GIT_TEST_INDEX_VERSION=@GIT_TEST_INDEX_VERSION@ -GIT_TEST_MERGE_TOOLS_DIR=@GIT_TEST_MERGE_TOOLS_DIR@ GIT_TEST_OPTS=@GIT_TEST_OPTS@ GIT_TEST_PERL_FATAL_WARNINGS=@GIT_TEST_PERL_FATAL_WARNINGS@ -GIT_TEST_POPATH=@GIT_TEST_POPATH@ GIT_TEST_TEMPLATE_DIR=@GIT_TEST_TEMPLATE_DIR@ GIT_TEST_TEXTDOMAINDIR=@GIT_TEST_TEXTDOMAINDIR@ GIT_TEST_UTF8_LOCALE=@GIT_TEST_UTF8_LOCALE@ @@ -45,4 +44,5 @@ TEST_OUTPUT_DIRECTORY=@TEST_OUTPUT_DIRECTORY@ TEST_SHELL_PATH=@TEST_SHELL_PATH@ USE_GETTEXT_SCHEME=@USE_GETTEXT_SCHEME@ USE_LIBPCRE2=@USE_LIBPCRE2@ +WITH_BREAKING_CHANGES=@WITH_BREAKING_CHANGES@ X=@X@ diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 570cc11622..b981598298 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,25 +1,33 @@ #!/bin/sh -DEF_VER=v2.48.1 +DEF_VER=v2.49.GIT LF=' ' -if test "$#" -ne 3 +if test "$#" -lt 2 || test "$#" -gt 3 then - echo >&2 "USAGE: $0 <SOURCE_DIR> <INPUT> <OUTPUT>" + echo >&2 "USAGE: $0 <SOURCE_DIR> (--format=<STRING>|<INPUT>) [<OUTPUT>]" exit 1 fi SOURCE_DIR="$1" -INPUT="$2" -OUTPUT="$3" -if ! test -f "$INPUT" -then - echo >&2 "Input is not a file: $INPUT" - exit 1 -fi +case "$2" in +--format=*) + INPUT="${2#--format=}" + ;; +*) + if ! test -f "$2" + then + echo >&2 "Input is not a file: $2" + exit 1 + fi + INPUT=$(cat "$2") + ;; +esac + +OUTPUT="$3" # Protect us from reading Git version information outside of the Git directory # in case it is not a repository itself, but embedded in an unrelated @@ -39,13 +47,9 @@ then test -d "${GIT_DIR:-.git}" || test -f "$SOURCE_DIR"/.git; } && - VN=$(git -C "$SOURCE_DIR" describe --match "v[0-9]*" HEAD 2>/dev/null) && + VN=$(git -C "$SOURCE_DIR" describe --dirty --match="v[0-9]*" 2>/dev/null) && case "$VN" in *$LF*) (exit 1) ;; - v[0-9]*) - git -C "$SOURCE_DIR" update-index -q --refresh - test -z "$(git -C "$SOURCE_DIR" diff-index --name-only HEAD --)" || - VN="$VN-dirty" ;; esac then VN=$(echo "$VN" | sed -e 's/-/./g'); @@ -78,19 +82,25 @@ read GIT_MAJOR_VERSION GIT_MINOR_VERSION GIT_MICRO_VERSION GIT_PATCH_LEVEL trail $(echo "$GIT_VERSION" 0 0 0 0 | tr '.a-zA-Z-' ' ') EOF -sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \ +REPLACED=$(printf "%s" "$INPUT" | sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \ -e "s|@GIT_MAJOR_VERSION@|$GIT_MAJOR_VERSION|" \ -e "s|@GIT_MINOR_VERSION@|$GIT_MINOR_VERSION|" \ -e "s|@GIT_MICRO_VERSION@|$GIT_MICRO_VERSION|" \ -e "s|@GIT_PATCH_LEVEL@|$GIT_PATCH_LEVEL|" \ -e "s|@GIT_BUILT_FROM_COMMIT@|$GIT_BUILT_FROM_COMMIT|" \ -e "s|@GIT_USER_AGENT@|$GIT_USER_AGENT|" \ - -e "s|@GIT_DATE@|$GIT_DATE|" \ - "$INPUT" >"$OUTPUT".$$+ + -e "s|@GIT_DATE@|$GIT_DATE|" +) -if ! test -f "$OUTPUT" || ! cmp "$OUTPUT".$$+ "$OUTPUT" >/dev/null +if test -z "$OUTPUT" then - mv "$OUTPUT".$$+ "$OUTPUT" + printf "%s\n" "$REPLACED" else - rm "$OUTPUT".$$+ + printf "%s\n" "$REPLACED" >"$OUTPUT".$$+ + if ! test -f "$OUTPUT" || ! cmp "$OUTPUT".$$+ "$OUTPUT" >/dev/null + then + mv "$OUTPUT".$$+ "$OUTPUT" + else + rm "$OUTPUT".$$+ + fi fi @@ -183,7 +183,8 @@ include shared.mak # byte-order mark (BOM) when writing UTF-16 or UTF-32 and always writes in # big-endian format. # -# Define NO_DEFLATE_BOUND if your zlib does not have deflateBound. +# Define NO_DEFLATE_BOUND if your zlib does not have deflateBound. Define +# ZLIB_NG if you want to use zlib-ng instead of zlib. # # Define NO_NORETURN if using buggy versions of gcc 4.6+ and profile feedback, # as the compiler can crash (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49299) @@ -193,7 +194,7 @@ include shared.mak # Linux, kernel 2.6.11 or newer is required for reliable sub-second file times # on file systems with exactly 1 ns or 1 s resolution. If you intend to use Git # on other file systems (e.g. CEPH, CIFS, NTFS, UDF), don't enable USE_NSEC. See -# Documentation/technical/racy-git.txt for details. +# Documentation/technical/racy-git.adoc for details. # # Define USE_ST_TIMESPEC if your "struct stat" uses "st_ctimespec" instead of # "st_ctim" @@ -416,6 +417,9 @@ include shared.mak # Define LINK_FUZZ_PROGRAMS if you want `make all` to also build the fuzz test # programs in oss-fuzz/. # +# Define INCLUDE_LIBGIT_RS if you want `make all` and `make test` to build and +# test the Rust crates in contrib/libgit-sys and contrib/libgit-rs. +# # === Optional library: libintl === # # Define NO_GETTEXT if you don't want Git output to be translated. @@ -657,6 +661,8 @@ CURL_CONFIG = curl-config GCOV = gcov STRIP = strip SPATCH = spatch +LD = ld +OBJCOPY = objcopy export TCL_PATH TCLTK_PATH @@ -675,6 +681,7 @@ FUZZ_OBJS = FUZZ_PROGRAMS = GIT_OBJS = LIB_OBJS = +LIBGIT_PUB_OBJS = SCALAR_OBJS = OBJECTS = OTHER_PROGRAMS = @@ -812,12 +819,14 @@ TEST_BUILTINS_OBJS += test-lazy-init-name-hash.o TEST_BUILTINS_OBJS += test-match-trees.o TEST_BUILTINS_OBJS += test-mergesort.o TEST_BUILTINS_OBJS += test-mktemp.o +TEST_BUILTINS_OBJS += test-name-hash.o TEST_BUILTINS_OBJS += test-online-cpus.o TEST_BUILTINS_OBJS += test-pack-mtimes.o TEST_BUILTINS_OBJS += test-parse-options.o TEST_BUILTINS_OBJS += test-parse-pathspec-file.o TEST_BUILTINS_OBJS += test-partial-clone.o TEST_BUILTINS_OBJS += test-path-utils.o +TEST_BUILTINS_OBJS += test-path-walk.o TEST_BUILTINS_OBJS += test-pcre2-config.o TEST_BUILTINS_OBJS += test-pkt-line.o TEST_BUILTINS_OBJS += test-proc-receive.o @@ -981,10 +990,11 @@ LIB_OBJS += combine-diff.o LIB_OBJS += commit-graph.o LIB_OBJS += commit-reach.o LIB_OBJS += commit.o +LIB_OBJS += common-exit.o +LIB_OBJS += common-init.o LIB_OBJS += compat/nonblock.o LIB_OBJS += compat/obstack.o LIB_OBJS += compat/terminal.o -LIB_OBJS += compat/zlib-uncompress2.o LIB_OBJS += compiler-tricks/not-constant.o LIB_OBJS += config.o LIB_OBJS += connect.o @@ -1095,6 +1105,7 @@ LIB_OBJS += parse-options.o LIB_OBJS += patch-delta.o LIB_OBJS += patch-ids.o LIB_OBJS += path.o +LIB_OBJS += path-walk.o LIB_OBJS += pathspec.o LIB_OBJS += pkt-line.o LIB_OBJS += preload-index.o @@ -1202,6 +1213,7 @@ BUILTIN_OBJS += builtin/am.o BUILTIN_OBJS += builtin/annotate.o BUILTIN_OBJS += builtin/apply.o BUILTIN_OBJS += builtin/archive.o +BUILTIN_OBJS += builtin/backfill.o BUILTIN_OBJS += builtin/bisect.o BUILTIN_OBJS += builtin/blame.o BUILTIN_OBJS += builtin/branch.o @@ -1231,6 +1243,7 @@ BUILTIN_OBJS += builtin/describe.o BUILTIN_OBJS += builtin/diagnose.o BUILTIN_OBJS += builtin/diff-files.o BUILTIN_OBJS += builtin/diff-index.o +BUILTIN_OBJS += builtin/diff-pairs.o BUILTIN_OBJS += builtin/diff-tree.o BUILTIN_OBJS += builtin/diff.o BUILTIN_OBJS += builtin/difftool.o @@ -1272,7 +1285,9 @@ BUILTIN_OBJS += builtin/mv.o BUILTIN_OBJS += builtin/name-rev.o BUILTIN_OBJS += builtin/notes.o BUILTIN_OBJS += builtin/pack-objects.o +ifndef WITH_BREAKING_CHANGES BUILTIN_OBJS += builtin/pack-redundant.o +endif BUILTIN_OBJS += builtin/pack-refs.o BUILTIN_OBJS += builtin/patch-id.o BUILTIN_OBJS += builtin/prune-packed.o @@ -1339,20 +1354,24 @@ THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/% THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/clar/% CLAR_TEST_SUITES += u-ctype +CLAR_TEST_SUITES += u-example-decorate +CLAR_TEST_SUITES += u-hash +CLAR_TEST_SUITES += u-hashmap +CLAR_TEST_SUITES += u-mem-pool +CLAR_TEST_SUITES += u-oid-array +CLAR_TEST_SUITES += u-oidmap +CLAR_TEST_SUITES += u-oidtree +CLAR_TEST_SUITES += u-prio-queue +CLAR_TEST_SUITES += u-reftable-tree +CLAR_TEST_SUITES += u-strbuf +CLAR_TEST_SUITES += u-strcmp-offset CLAR_TEST_SUITES += u-strvec CLAR_TEST_PROG = $(UNIT_TEST_BIN)/unit-tests$(X) CLAR_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(CLAR_TEST_SUITES)) CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/clar/clar.o CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o +CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/lib-oid.o -UNIT_TEST_PROGRAMS += t-example-decorate -UNIT_TEST_PROGRAMS += t-hash -UNIT_TEST_PROGRAMS += t-hashmap -UNIT_TEST_PROGRAMS += t-mem-pool -UNIT_TEST_PROGRAMS += t-oid-array -UNIT_TEST_PROGRAMS += t-oidmap -UNIT_TEST_PROGRAMS += t-oidtree -UNIT_TEST_PROGRAMS += t-prio-queue UNIT_TEST_PROGRAMS += t-reftable-basics UNIT_TEST_PROGRAMS += t-reftable-block UNIT_TEST_PROGRAMS += t-reftable-merged @@ -1361,14 +1380,10 @@ UNIT_TEST_PROGRAMS += t-reftable-reader UNIT_TEST_PROGRAMS += t-reftable-readwrite UNIT_TEST_PROGRAMS += t-reftable-record UNIT_TEST_PROGRAMS += t-reftable-stack -UNIT_TEST_PROGRAMS += t-reftable-tree -UNIT_TEST_PROGRAMS += t-strbuf -UNIT_TEST_PROGRAMS += t-strcmp-offset UNIT_TEST_PROGRAMS += t-trailer UNIT_TEST_PROGRAMS += t-urlmatch-normalization UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS)) UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o -UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-oid.o UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-reftable.o # xdiff and reftable libs may in turn depend on what is in libgit.a @@ -1689,11 +1704,20 @@ else endif IMAP_SEND_LDFLAGS += $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO) -ifdef ZLIB_PATH - BASIC_CFLAGS += -I$(ZLIB_PATH)/include - EXTLIBS += $(call libpath_template,$(ZLIB_PATH)/$(lib)) +ifdef ZLIB_NG + BASIC_CFLAGS += -DHAVE_ZLIB_NG + ifdef ZLIB_NG_PATH + BASIC_CFLAGS += -I$(ZLIB_NG_PATH)/include + EXTLIBS += $(call libpath_template,$(ZLIB_NG_PATH)/$(lib)) + endif + EXTLIBS += -lz-ng +else + ifdef ZLIB_PATH + BASIC_CFLAGS += -I$(ZLIB_PATH)/include + EXTLIBS += $(call libpath_template,$(ZLIB_PATH)/$(lib)) + endif + EXTLIBS += -lz endif -EXTLIBS += -lz ifndef NO_OPENSSL OPENSSL_LIBSSL = -lssl @@ -2235,6 +2259,16 @@ ifdef FSMONITOR_OS_SETTINGS COMPAT_OBJS += compat/fsmonitor/fsm-path-utils-$(FSMONITOR_OS_SETTINGS).o endif +ifdef WITH_BREAKING_CHANGES + BASIC_CFLAGS += -DWITH_BREAKING_CHANGES +endif + +ifdef INCLUDE_LIBGIT_RS + # Enable symbol hiding in contrib/libgit-sys/libgitpub.a without making + # us rebuild the whole tree every time we run a Rust build. + BASIC_CFLAGS += -fvisibility=hidden +endif + ifeq ($(TCLTK_PATH),) NO_TCLTK = NoThanks endif @@ -2529,17 +2563,17 @@ $(BUILT_INS): git$X config-list.h: generate-configlist.sh -config-list.h: Documentation/*config.txt Documentation/config/*.txt +config-list.h: Documentation/*config.adoc Documentation/config/*.adoc $(QUIET_GEN)$(SHELL_PATH) ./generate-configlist.sh . $@ command-list.h: generate-cmdlist.sh command-list.txt -command-list.h: $(wildcard Documentation/git*.txt) +command-list.h: $(wildcard Documentation/git*.adoc) $(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh \ $(patsubst %,--exclude-program %,$(EXCLUDED_PROGRAMS)) \ . $@ -hook-list.h: generate-hooklist.sh Documentation/githooks.txt +hook-list.h: generate-hooklist.sh Documentation/githooks.adoc $(QUIET_GEN)$(SHELL_PATH) ./generate-hooklist.sh . $@ SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):\ @@ -2731,6 +2765,10 @@ OBJECTS += $(UNIT_TEST_OBJS) OBJECTS += $(CLAR_TEST_OBJS) OBJECTS += $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS)) +ifdef INCLUDE_LIBGIT_RS + OBJECTS += contrib/libgit-sys/public_symbol_export.o +endif + ifndef NO_CURL OBJECTS += http.o http-walker.o remote-curl.o endif @@ -3157,14 +3195,13 @@ GIT-BUILD-OPTIONS: FORCE -e "s|@GIT_PERF_MAKE_OPTS@|\'$(GIT_PERF_MAKE_OPTS)\'|" \ -e "s|@GIT_PERF_REPEAT_COUNT@|\'$(GIT_PERF_REPEAT_COUNT)\'|" \ -e "s|@GIT_PERF_REPO@|\'$(GIT_PERF_REPO)\'|" \ + -e "s|@GIT_SOURCE_DIR@|\'$(shell pwd)\'|" \ -e "s|@GIT_TEST_CMP@|\'$(GIT_TEST_CMP)\'|" \ -e "s|@GIT_TEST_CMP_USE_COPIED_CONTEXT@|\'$(GIT_TEST_CMP_USE_COPIED_CONTEXT)\'|" \ -e "s|@GIT_TEST_GITPERLLIB@|\'$(shell pwd)/perl/build/lib\'|" \ -e "s|@GIT_TEST_INDEX_VERSION@|\'$(GIT_TEST_INDEX_VERSION)\'|" \ - -e "s|@GIT_TEST_MERGE_TOOLS_DIR@|\'$(shell pwd)/mergetools\'|" \ -e "s|@GIT_TEST_OPTS@|\'$(GIT_TEST_OPTS)\'|" \ -e "s|@GIT_TEST_PERL_FATAL_WARNINGS@|\'$(GIT_TEST_PERL_FATAL_WARNINGS)\'|" \ - -e "s|@GIT_TEST_POPATH@|\'$(shell pwd)/po\'|" \ -e "s|@GIT_TEST_TEMPLATE_DIR@|\'$(shell pwd)/templates/blt\'|" \ -e "s|@GIT_TEST_TEXTDOMAINDIR@|\'$(shell pwd)/po/build/locale\'|" \ -e "s|@GIT_TEST_UTF8_LOCALE@|\'$(GIT_TEST_UTF8_LOCALE)\'|" \ @@ -3193,6 +3230,7 @@ GIT-BUILD-OPTIONS: FORCE -e "s|@TEST_SHELL_PATH@|\'$(TEST_SHELL_PATH_SQ)\'|" \ -e "s|@USE_GETTEXT_SCHEME@|\'$(USE_GETTEXT_SCHEME)\'|" \ -e "s|@USE_LIBPCRE2@|\'$(USE_LIBPCRE2)\'|" \ + -e "s|@WITH_BREAKING_CHANGES@|\'$(WITH_BREAKING_CHANGES)\'|" \ -e "s|@X@|\'$(X)\'|" \ GIT-BUILD-OPTIONS.in >$@+ @if grep -q '^[A-Z][A-Z_]*=@.*@$$' $@+; then echo "Unsubstituted build options in $@" >&2 && exit 1; fi @@ -3725,6 +3763,10 @@ clean: profile-clean coverage-clean cocciclean $(RM) $(htmldocs).tar.gz $(manpages).tar.gz $(MAKE) -C Documentation/ clean $(RM) Documentation/GIT-EXCLUDED-PROGRAMS + $(RM) -r contrib/libgit-sys/target contrib/libgit-rs/target + $(RM) contrib/libgit-sys/partial_symbol_export.o + $(RM) contrib/libgit-sys/hidden_symbol_export.o + $(RM) contrib/libgit-sys/libgitpub.a ifndef NO_PERL $(RM) -r perl/build/ endif @@ -3886,3 +3928,31 @@ $(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT- build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X $(MAKE) -C t/ unit-tests + +.PHONY: libgit-sys libgit-rs +libgit-sys libgit-rs: + $(QUIET)(\ + cd contrib/$@ && \ + cargo build \ + ) +ifdef INCLUDE_LIBGIT_RS +all:: libgit-sys libgit-rs +endif + +LIBGIT_PUB_OBJS += contrib/libgit-sys/public_symbol_export.o +LIBGIT_PUB_OBJS += libgit.a +LIBGIT_PUB_OBJS += reftable/libreftable.a +LIBGIT_PUB_OBJS += xdiff/lib.a + +LIBGIT_PARTIAL_EXPORT = contrib/libgit-sys/partial_symbol_export.o + +LIBGIT_HIDDEN_EXPORT = contrib/libgit-sys/hidden_symbol_export.o + +$(LIBGIT_PARTIAL_EXPORT): $(LIBGIT_PUB_OBJS) + $(LD) -r $^ -o $@ + +$(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT) + $(OBJCOPY) --localize-hidden $^ $@ + +contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT) + $(AR) $(ARFLAGS) $@ $^ @@ -17,15 +17,15 @@ Please read the file [INSTALL][] for installation instructions. Many Git online resources are accessible from <https://git-scm.com/> including full documentation and Git related tools. -See [Documentation/gittutorial.txt][] to get started, then see -[Documentation/giteveryday.txt][] for a useful minimum set of commands, and -`Documentation/git-<commandname>.txt` for documentation of each command. +See [Documentation/gittutorial.adoc][] to get started, then see +[Documentation/giteveryday.adoc][] for a useful minimum set of commands, and +`Documentation/git-<commandname>.adoc` for documentation of each command. If git has been correctly installed, then the tutorial can also be read with `man gittutorial` or `git help tutorial`, and the documentation of each command with `man git-<commandname>` or `git help <commandname>`. -CVS users may also want to read [Documentation/gitcvs-migration.txt][] +CVS users may also want to read [Documentation/gitcvs-migration.adoc][] (`man gitcvs-migration` or `git help cvs-migration` if git is installed). @@ -66,9 +66,9 @@ and the name as (depending on your mood): - "goddamn idiotic truckload of sh*t": when it breaks [INSTALL]: INSTALL -[Documentation/gittutorial.txt]: Documentation/gittutorial.txt -[Documentation/giteveryday.txt]: Documentation/giteveryday.txt -[Documentation/gitcvs-migration.txt]: Documentation/gitcvs-migration.txt +[Documentation/gittutorial.adoc]: Documentation/gittutorial.adoc +[Documentation/giteveryday.adoc]: Documentation/giteveryday.adoc +[Documentation/gitcvs-migration.adoc]: Documentation/gitcvs-migration.adoc [Documentation/SubmittingPatches]: Documentation/SubmittingPatches [Documentation/CodingGuidelines]: Documentation/CodingGuidelines [po/README.md]: po/README.md @@ -1 +1 @@ -Documentation/RelNotes/2.48.1.txt
\ No newline at end of file +Documentation/RelNotes/2.50.0.adoc
\ No newline at end of file diff --git a/add-interactive.c b/add-interactive.c index d0f8c10e6f..97ff35b6f1 100644 --- a/add-interactive.c +++ b/add-interactive.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -72,14 +71,14 @@ void init_add_i_state(struct add_i_state *s, struct repository *r) s->use_color ? GIT_COLOR_RESET : "", COLOR_MAXLEN); FREE_AND_NULL(s->interactive_diff_filter); - git_config_get_string("interactive.difffilter", - &s->interactive_diff_filter); + repo_config_get_string(r, "interactive.difffilter", + &s->interactive_diff_filter); FREE_AND_NULL(s->interactive_diff_algorithm); - git_config_get_string("diff.algorithm", - &s->interactive_diff_algorithm); + repo_config_get_string(r, "diff.algorithm", + &s->interactive_diff_algorithm); - git_config_get_bool("interactive.singlekey", &s->use_single_key); + repo_config_get_bool(r, "interactive.singlekey", &s->use_single_key); if (s->use_single_key) setbuf(stdin, NULL); } @@ -535,7 +534,7 @@ static int get_modified_files(struct repository *r, size_t *binary_count) { struct object_id head_oid; - int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(the_repository), + int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(r), "HEAD", RESOLVE_REF_READING, &head_oid, NULL); struct collection_status s = { 0 }; @@ -560,7 +559,7 @@ static int get_modified_files(struct repository *r, s.skip_unseen = filter && i; opt.def = is_initial ? - empty_tree_oid_hex(the_repository->hash_algo) : oid_to_hex(&head_oid); + empty_tree_oid_hex(r->hash_algo) : oid_to_hex(&head_oid); repo_init_revisions(r, &rev, NULL); setup_revisions(0, NULL, &rev, &opt); @@ -765,7 +764,7 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps, size_t count, i, j; struct object_id oid; - int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(the_repository), + int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(s->r), "HEAD", RESOLVE_REF_READING, &oid, NULL); @@ -996,7 +995,7 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps, ssize_t count, i; struct object_id oid; - int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(the_repository), + int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(s->r), "HEAD", RESOLVE_REF_READING, &oid, NULL); diff --git a/add-patch.c b/add-patch.c index 7b598e14df..95c67d8c80 100644 --- a/add-patch.c +++ b/add-patch.c @@ -1464,7 +1464,7 @@ static int patch_update_file(struct add_p_state *s, if (file_diff->hunk_nr) { if (rendered_hunk_index != hunk_index) { if (use_pager) { - setup_pager(); + setup_pager(the_repository); sigchain_push(SIGPIPE, SIG_IGN); } render_hunk(s, hunk, 0, colored, &s->buf); @@ -7,7 +7,7 @@ struct string_list; * To add a new advice, you need to: * Define a new advice_type. * Add a new entry to advice_setting array. - * Add the new config variable to Documentation/config/advice.txt. + * Add the new config variable to Documentation/config/advice.adoc. * Call advise_if_enabled to print your advice. */ enum advice_type { @@ -82,7 +82,7 @@ static int parse_whitespace_option(struct apply_state *state, const char *option } /* * Please update $__git_whitespacelist in git-completion.bash, - * Documentation/git-apply.txt, and Documentation/git-am.txt + * Documentation/git-apply.adoc, and Documentation/git-am.adoc * when you add new options. */ return error(_("unrecognized whitespace option '%s'"), option); @@ -1423,7 +1423,10 @@ static int parse_num(const char *line, unsigned long *p) if (!isdigit(*line)) return 0; + errno = 0; *p = strtoul(line, &ptr, 10); + if (errno) + return 0; return ptr - line; } diff --git a/archive-tar.c b/archive-tar.c index e7b3489e1e..0edf13fba7 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -473,9 +473,7 @@ static const char internal_gzip_command[] = "git archive gzip"; static int write_tar_filter_archive(const struct archiver *ar, struct archiver_args *args) { -#if ZLIB_VERNUM >= 0x1221 struct gz_header_s gzhead = { .os = 3 }; /* Unix, for reproducibility */ -#endif struct strbuf cmd = STRBUF_INIT; struct child_process filter = CHILD_PROCESS_INIT; int r; @@ -486,10 +484,8 @@ static int write_tar_filter_archive(const struct archiver *ar, if (!strcmp(ar->filter_command, internal_gzip_command)) { write_block = tgz_write_block; git_deflate_init_gzip(&gzstream, args->compression_level); -#if ZLIB_VERNUM >= 0x1221 if (deflateSetHeader(&gzstream.z, &gzhead) != Z_OK) BUG("deflateSetHeader() called too late"); -#endif gzstream.next_out = outbuf; gzstream.avail_out = sizeof(outbuf); @@ -7,6 +7,7 @@ #include "convert.h" #include "environment.h" #include "gettext.h" +#include "git-zlib.h" #include "hex.h" #include "object-name.h" #include "path.h" @@ -780,10 +780,10 @@ static struct commit *get_commit_reference(struct repository *r, } static struct commit **get_bad_and_good_commits(struct repository *r, - int *rev_nr) + size_t *rev_nr) { struct commit **rev; - int i, n = 0; + size_t i, n = 0; ALLOC_ARRAY(rev, 1 + good_revs.nr); rev[n++] = get_commit_reference(r, current_bad_oid); @@ -855,7 +855,7 @@ static void handle_skipped_merge_base(const struct object_id *mb) * for early success, this will be converted back to 0 in * check_good_are_ancestors_of_bad(). */ -static enum bisect_error check_merge_bases(int rev_nr, struct commit **rev, int no_checkout) +static enum bisect_error check_merge_bases(size_t rev_nr, struct commit **rev, int no_checkout) { enum bisect_error res = BISECT_OK; struct commit_list *result = NULL; @@ -887,7 +887,7 @@ static enum bisect_error check_merge_bases(int rev_nr, struct commit **rev, int return res; } -static int check_ancestors(struct repository *r, int rev_nr, +static int check_ancestors(struct repository *r, size_t rev_nr, struct commit **rev, const char *prefix) { struct strvec rev_argv = STRVEC_INIT; @@ -922,14 +922,15 @@ static enum bisect_error check_good_are_ancestors_of_bad(struct repository *r, { char *filename; struct stat st; - int fd, rev_nr; + int fd; + size_t rev_nr; enum bisect_error res = BISECT_OK; struct commit **rev; if (!current_bad_oid) return error(_("a %s revision is needed"), term_bad); - filename = git_pathdup("BISECT_ANCESTORS_OK"); + filename = repo_git_path(the_repository, "BISECT_ANCESTORS_OK"); /* Check if file BISECT_ANCESTORS_OK exists. */ if (!stat(filename, &st) && S_ISREG(st.st_mode)) @@ -397,7 +397,7 @@ static void prepare_checked_out_branches(void) worktrees = get_worktrees(); while (worktrees[i]) { - char *old; + char *old, *wt_gitdir; struct wt_status_state state = { 0 }; struct worktree *wt = worktrees[i++]; struct string_list update_refs = STRING_LIST_INIT_DUP; @@ -437,7 +437,8 @@ static void prepare_checked_out_branches(void) } wt_status_state_free_buffers(&state); - if (!sequencer_get_update_refs_state(get_worktree_git_dir(wt), + wt_gitdir = get_worktree_git_dir(wt); + if (!sequencer_get_update_refs_state(wt_gitdir, &update_refs)) { struct string_list_item *item; for_each_string_list_item(item, &update_refs) { @@ -448,6 +449,8 @@ static void prepare_checked_out_branches(void) } string_list_clear(&update_refs, 1); } + + free(wt_gitdir); } free_worktrees(worktrees); @@ -63,7 +63,7 @@ * * . Add tests to `t/` directory. * - * . Write documentation in `Documentation/git-foo.txt`. + * . Write documentation in `Documentation/git-foo.adoc`. * * . Add an entry for `git-foo` to `command-list.txt`. * @@ -120,6 +120,7 @@ int cmd_am(int argc, const char **argv, const char *prefix, struct repository *r int cmd_annotate(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_apply(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_archive(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_backfill(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_bisect(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_blame(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_branch(int argc, const char **argv, const char *prefix, struct repository *repo); @@ -152,6 +153,7 @@ int cmd_diagnose(int argc, const char **argv, const char *prefix, struct reposit int cmd_diff_files(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_diff_index(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_diff(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_diff_pairs(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_diff_tree(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_difftool(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_env__helper(int argc, const char **argv, const char *prefix, struct repository *repo); diff --git a/builtin/am.c b/builtin/am.c index 1338b606fe..3b61bd4c33 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -31,7 +31,7 @@ #include "preload-index.h" #include "sequencer.h" #include "revision.h" -#include "merge-recursive.h" +#include "merge-ort-wrappers.h" #include "log-tree.h" #include "notes-utils.h" #include "rerere.h" @@ -158,7 +158,7 @@ static void am_state_init(struct am_state *state) memset(state, 0, sizeof(*state)); - state->dir = git_pathdup("rebase-apply"); + state->dir = repo_git_path(the_repository, "rebase-apply"); state->prec = 4; @@ -1211,7 +1211,7 @@ static int parse_mail(struct am_state *state, const char *mail) int ret = 0; struct mailinfo mi; - setup_mailinfo(&mi); + setup_mailinfo(the_repository, &mi); if (state->utf8) mi.metainfo_charset = get_commit_output_encoding(); @@ -1638,12 +1638,13 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa o.branch1 = "HEAD"; their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg); o.branch2 = their_tree_name; + o.ancestor = "constructed fake ancestor"; o.detect_directory_renames = MERGE_DIRECTORY_RENAMES_NONE; if (state->quiet) o.verbosity = 0; - if (merge_recursive_generic(&o, &our_tree, &their_tree, 1, bases, &result)) { + if (merge_ort_generic(&o, &our_tree, &their_tree, 1, bases, &result)) { repo_rerere(the_repository, state->allow_rerere_autoupdate); free(their_tree_name); return error(_("Failed to merge in the changes.")); @@ -1786,7 +1787,7 @@ static int do_interactive(struct am_state *state) } strbuf_release(&msg); } else if (*reply == 'v' || *reply == 'V') { - const char *pager = git_pager(1); + const char *pager = git_pager(the_repository, 1); struct child_process cp = CHILD_PROCESS_INIT; if (!pager) @@ -2246,7 +2247,7 @@ static int show_patch(struct am_state *state, enum resume_type resume_mode) if (len < 0) die_errno(_("failed to read '%s'"), patch_path); - setup_pager(); + setup_pager(the_repository); write_in_full(1, sb.buf, sb.len); strbuf_release(&sb); return 0; @@ -2427,8 +2428,7 @@ int cmd_am(int argc, OPT_END() }; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(usage, options); + show_usage_with_options_if_asked(argc, argv, usage, options); git_config(git_default_config, NULL); diff --git a/builtin/backfill.c b/builtin/backfill.c new file mode 100644 index 0000000000..33e1ea2f84 --- /dev/null +++ b/builtin/backfill.c @@ -0,0 +1,147 @@ +/* We need this macro to access core_apply_sparse_checkout */ +#define USE_THE_REPOSITORY_VARIABLE + +#include "builtin.h" +#include "git-compat-util.h" +#include "config.h" +#include "parse-options.h" +#include "repository.h" +#include "commit.h" +#include "dir.h" +#include "environment.h" +#include "hex.h" +#include "tree.h" +#include "tree-walk.h" +#include "object.h" +#include "object-store-ll.h" +#include "oid-array.h" +#include "oidset.h" +#include "promisor-remote.h" +#include "strmap.h" +#include "string-list.h" +#include "revision.h" +#include "trace2.h" +#include "progress.h" +#include "packfile.h" +#include "path-walk.h" + +static const char * const builtin_backfill_usage[] = { + N_("git backfill [--min-batch-size=<n>] [--[no-]sparse]"), + NULL +}; + +struct backfill_context { + struct repository *repo; + struct oid_array current_batch; + size_t min_batch_size; + int sparse; +}; + +static void backfill_context_clear(struct backfill_context *ctx) +{ + oid_array_clear(&ctx->current_batch); +} + +static void download_batch(struct backfill_context *ctx) +{ + promisor_remote_get_direct(ctx->repo, + ctx->current_batch.oid, + ctx->current_batch.nr); + oid_array_clear(&ctx->current_batch); + + /* + * We likely have a new packfile. Add it to the packed list to + * avoid possible duplicate downloads of the same objects. + */ + reprepare_packed_git(ctx->repo); +} + +static int fill_missing_blobs(const char *path UNUSED, + struct oid_array *list, + enum object_type type, + void *data) +{ + struct backfill_context *ctx = data; + + if (type != OBJ_BLOB) + return 0; + + for (size_t i = 0; i < list->nr; i++) { + if (!has_object(ctx->repo, &list->oid[i], + OBJECT_INFO_FOR_PREFETCH)) + oid_array_append(&ctx->current_batch, &list->oid[i]); + } + + if (ctx->current_batch.nr >= ctx->min_batch_size) + download_batch(ctx); + + return 0; +} + +static int do_backfill(struct backfill_context *ctx) +{ + struct rev_info revs; + struct path_walk_info info = PATH_WALK_INFO_INIT; + int ret; + + if (ctx->sparse) { + CALLOC_ARRAY(info.pl, 1); + if (get_sparse_checkout_patterns(info.pl)) { + path_walk_info_clear(&info); + return error(_("problem loading sparse-checkout")); + } + } + + repo_init_revisions(ctx->repo, &revs, ""); + handle_revision_arg("HEAD", &revs, 0, 0); + + info.blobs = 1; + info.tags = info.commits = info.trees = 0; + + info.revs = &revs; + info.path_fn = fill_missing_blobs; + info.path_fn_data = ctx; + + ret = walk_objects_by_path(&info); + + /* Download the objects that did not fill a batch. */ + if (!ret) + download_batch(ctx); + + path_walk_info_clear(&info); + release_revisions(&revs); + return ret; +} + +int cmd_backfill(int argc, const char **argv, const char *prefix, struct repository *repo) +{ + int result; + struct backfill_context ctx = { + .repo = repo, + .current_batch = OID_ARRAY_INIT, + .min_batch_size = 50000, + .sparse = 0, + }; + struct option options[] = { + OPT_INTEGER(0, "min-batch-size", &ctx.min_batch_size, + N_("Minimum number of objects to request at a time")), + OPT_BOOL(0, "sparse", &ctx.sparse, + N_("Restrict the missing objects to the current sparse-checkout")), + OPT_END(), + }; + + show_usage_with_options_if_asked(argc, argv, + builtin_backfill_usage, options); + + argc = parse_options(argc, argv, prefix, options, builtin_backfill_usage, + 0); + + repo_config(repo, git_default_config, NULL); + + if (ctx.sparse < 0) + ctx.sparse = core_apply_sparse_checkout; + + result = do_backfill(&ctx); + backfill_context_clear(&ctx); + return result; +} diff --git a/builtin/blame.c b/builtin/blame.c index 7555c445ab..c470654c7e 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -1194,14 +1194,16 @@ parse_done: sb.found_guilty_entry = &found_guilty_entry; sb.found_guilty_entry_data = π if (show_progress) - pi.progress = start_delayed_progress(_("Blaming lines"), num_lines); + pi.progress = start_delayed_progress(the_repository, + _("Blaming lines"), + num_lines); assign_blame(&sb, opt); stop_progress(&pi.progress); if (!incremental) - setup_pager(); + setup_pager(the_repository); else goto cleanup; diff --git a/builtin/branch.c b/builtin/branch.c index 6e7b0cfddb..c150131bd9 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -473,7 +473,7 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin if (verify_ref_format(format)) die(_("unable to parse format string")); - filter_ahead_behind(the_repository, format, &array); + filter_ahead_behind(the_repository, &array); ref_array_sort(sorting, &array); if (column_active(colopts)) { @@ -784,8 +784,8 @@ int cmd_branch(int argc, filter.kind = FILTER_REFS_BRANCHES; filter.abbrev = -1; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_branch_usage, options); + show_usage_with_options_if_asked(argc, argv, + builtin_branch_usage, options); /* * Try to set sort keys from config. If config does not set any, @@ -884,7 +884,6 @@ int cmd_branch(int argc, string_list_clear(&output, 0); ref_sorting_release(sorting); ref_filter_clear(&filter); - ref_format_clear(&format); ret = 0; goto out; diff --git a/builtin/bugreport.c b/builtin/bugreport.c index 7c2df035c9..66d64bfd5a 100644 --- a/builtin/bugreport.c +++ b/builtin/bugreport.c @@ -12,10 +12,10 @@ #include "diagnose.h" #include "object-file.h" #include "setup.h" +#include "version.h" static void get_system_info(struct strbuf *sys_info) { - struct utsname uname_info; char *shell = NULL; /* get git version from native cmd */ @@ -24,16 +24,7 @@ static void get_system_info(struct strbuf *sys_info) /* system call for other version info */ strbuf_addstr(sys_info, "uname: "); - if (uname(&uname_info)) - strbuf_addf(sys_info, _("uname() failed with error '%s' (%d)\n"), - strerror(errno), - errno); - else - strbuf_addf(sys_info, "%s %s %s %s\n", - uname_info.sysname, - uname_info.release, - uname_info.version, - uname_info.machine); + get_uname_info(sys_info, 1); strbuf_addstr(sys_info, _("compiler info: ")); get_compiler_info(sys_info); @@ -167,7 +158,7 @@ int cmd_bugreport(int argc, strbuf_addftime(&zip_path, option_suffix, localtime_r(&now, &tm), 0, 0); strbuf_addstr(&zip_path, ".zip"); - if (create_diagnostics_archive(&zip_path, diagnose)) + if (create_diagnostics_archive(the_repository, &zip_path, diagnose)) die_errno(_("unable to create diagnostics archive %s"), zip_path.buf); strbuf_release(&zip_path); diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c index df00b5ee13..be2cebe121 100644 --- a/builtin/check-mailmap.c +++ b/builtin/check-mailmap.c @@ -35,7 +35,7 @@ static void check_mailmap(struct string_list *mailmap, const char *contact) mail = ident.mail_begin; maillen = ident.mail_end - ident.mail_begin; } else { - name = NULL; + name = ""; namelen = 0; mail = contact; maillen = strlen(contact); diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c index cef1ffe3ce..5d80afeec0 100644 --- a/builtin/check-ref-format.c +++ b/builtin/check-ref-format.c @@ -64,8 +64,8 @@ int cmd_check_ref_format(int argc, BUG_ON_NON_EMPTY_PREFIX(prefix); - if (argc == 2 && !strcmp(argv[1], "-h")) - usage(builtin_check_ref_format_usage); + show_usage_if_asked(argc, argv, + builtin_check_ref_format_usage); if (argc == 3 && !strcmp(argv[1], "--branch")) return check_ref_format_branch(argv[2]); diff --git a/builtin/checkout--worker.c b/builtin/checkout--worker.c index b81002a1df..da9345a44b 100644 --- a/builtin/checkout--worker.c +++ b/builtin/checkout--worker.c @@ -128,9 +128,9 @@ int cmd_checkout__worker(int argc, OPT_END() }; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(checkout_worker_usage, - checkout_worker_options); + show_usage_with_options_if_asked(argc, argv, + checkout_worker_usage, + checkout_worker_options); git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, checkout_worker_options, diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index a81501098d..7f74bc702f 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -5,7 +5,6 @@ * */ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "builtin.h" @@ -68,10 +67,10 @@ static void write_tempfile_record(const char *name, const char *prefix) } } -static int checkout_file(const char *name, const char *prefix) +static int checkout_file(struct index_state *index, const char *name, const char *prefix) { int namelen = strlen(name); - int pos = index_name_pos(the_repository->index, name, namelen); + int pos = index_name_pos(index, name, namelen); int has_same_name = 0; int is_file = 0; int is_skipped = 1; @@ -81,8 +80,8 @@ static int checkout_file(const char *name, const char *prefix) if (pos < 0) pos = -pos - 1; - while (pos <the_repository->index->cache_nr) { - struct cache_entry *ce =the_repository->index->cache[pos]; + while (pos < index->cache_nr) { + struct cache_entry *ce = index->cache[pos]; if (ce_namelen(ce) != namelen || memcmp(ce->name, name, namelen)) break; @@ -137,13 +136,13 @@ static int checkout_file(const char *name, const char *prefix) return -1; } -static int checkout_all(const char *prefix, int prefix_length) +static int checkout_all(struct index_state *index, const char *prefix, int prefix_length) { int i, errs = 0; struct cache_entry *last_ce = NULL; - for (i = 0; i < the_repository->index->cache_nr ; i++) { - struct cache_entry *ce = the_repository->index->cache[i]; + for (i = 0; i < index->cache_nr ; i++) { + struct cache_entry *ce = index->cache[i]; if (S_ISSPARSEDIR(ce->ce_mode)) { if (!ce_skip_worktree(ce)) @@ -156,8 +155,8 @@ static int checkout_all(const char *prefix, int prefix_length) * first entry inside the expanded sparse directory). */ if (ignore_skip_worktree) { - ensure_full_index(the_repository->index); - ce = the_repository->index->cache[i]; + ensure_full_index(index); + ce = index->cache[i]; } } @@ -213,7 +212,7 @@ static int option_parse_stage(const struct option *opt, int cmd_checkout_index(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i; struct lock_file lock_file = LOCK_INIT; @@ -250,22 +249,22 @@ int cmd_checkout_index(int argc, OPT_END() }; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_checkout_index_usage, - builtin_checkout_index_options); - git_config(git_default_config, NULL); + show_usage_with_options_if_asked(argc, argv, + builtin_checkout_index_usage, + builtin_checkout_index_options); + repo_config(repo, git_default_config, NULL); prefix_length = prefix ? strlen(prefix) : 0; - prepare_repo_settings(the_repository); - the_repository->settings.command_requires_full_index = 0; + prepare_repo_settings(repo); + repo->settings.command_requires_full_index = 0; - if (repo_read_index(the_repository) < 0) { + if (repo_read_index(repo) < 0) { die("invalid cache"); } argc = parse_options(argc, argv, prefix, builtin_checkout_index_options, builtin_checkout_index_usage, 0); - state.istate = the_repository->index; + state.istate = repo->index; state.force = force; state.quiet = quiet; state.not_new = not_new; @@ -285,8 +284,8 @@ int cmd_checkout_index(int argc, */ if (index_opt && !state.base_dir_len && !to_tempfile) { state.refresh_cache = 1; - state.istate = the_repository->index; - repo_hold_locked_index(the_repository, &lock_file, + state.istate = repo->index; + repo_hold_locked_index(repo, &lock_file, LOCK_DIE_ON_ERROR); } @@ -304,7 +303,7 @@ int cmd_checkout_index(int argc, if (read_from_stdin) die("git checkout-index: don't mix '--stdin' and explicit filenames"); p = prefix_path(prefix, prefix_length, arg); - err |= checkout_file(p, prefix); + err |= checkout_file(repo->index, p, prefix); free(p); } @@ -326,7 +325,7 @@ int cmd_checkout_index(int argc, strbuf_swap(&buf, &unquoted); } p = prefix_path(prefix, prefix_length, buf.buf); - err |= checkout_file(p, prefix); + err |= checkout_file(repo->index, p, prefix); free(p); } strbuf_release(&unquoted); @@ -334,7 +333,7 @@ int cmd_checkout_index(int argc, } if (all) - err |= checkout_all(prefix, prefix_length); + err |= checkout_all(repo->index, prefix, prefix_length); if (pc_workers > 1) err |= run_parallel_checkout(&state, pc_workers, pc_threshold, @@ -344,7 +343,7 @@ int cmd_checkout_index(int argc, return 1; if (is_lock_file_locked(&lock_file) && - write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK)) + write_locked_index(repo->index, &lock_file, COMMIT_LOCK)) die("Unable to write new index file"); return 0; } diff --git a/builtin/clone.c b/builtin/clone.c index fd001d800c..88276e5b7a 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -56,42 +56,30 @@ * - dropping use-separate-remote and no-separate-remote compatibility * */ -static const char * const builtin_clone_usage[] = { - N_("git clone [<options>] [--] <repo> [<dir>]"), - NULL + +struct clone_opts { + int wants_head; + int detach; }; +#define CLONE_OPTS_INIT { \ + .wants_head = 1 /* default enabled */ \ +} static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1; static int option_local = -1, option_no_hardlinks, option_shared; -static int option_no_tags; +static int option_tags = 1; /* default enabled */ static int option_shallow_submodules; -static int option_reject_shallow = -1; /* unspecified */ static int config_reject_shallow = -1; /* unspecified */ -static int deepen; -static char *option_template, *option_depth, *option_since; -static char *option_origin = NULL; static char *remote_name = NULL; static char *option_branch = NULL; -static struct string_list option_not = STRING_LIST_INIT_NODUP; -static const char *real_git_dir; -static const char *ref_format; -static const char *option_upload_pack = "git-upload-pack"; static int option_verbosity; -static int option_progress = -1; -static int option_sparse_checkout; -static enum transport_family family; -static struct string_list option_config = STRING_LIST_INIT_NODUP; static struct string_list option_required_reference = STRING_LIST_INIT_NODUP; static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP; -static int option_dissociate; static int max_jobs = -1; static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP; static struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT; -static int option_filter_submodules = -1; /* unspecified */ static int config_filter_submodules = -1; /* unspecified */ -static struct string_list server_options = STRING_LIST_INIT_NODUP; static int option_remote_submodules; -static const char *bundle_uri; static int recurse_submodules_cb(const struct option *opt, const char *arg, int unset) @@ -107,78 +95,6 @@ static int recurse_submodules_cb(const struct option *opt, return 0; } -static struct option builtin_clone_options[] = { - OPT__VERBOSITY(&option_verbosity), - OPT_BOOL(0, "progress", &option_progress, - N_("force progress reporting")), - OPT_BOOL(0, "reject-shallow", &option_reject_shallow, - N_("don't clone shallow repository")), - OPT_BOOL('n', "no-checkout", &option_no_checkout, - N_("don't create a checkout")), - OPT_BOOL(0, "bare", &option_bare, N_("create a bare repository")), - OPT_HIDDEN_BOOL(0, "naked", &option_bare, - N_("create a bare repository")), - OPT_BOOL(0, "mirror", &option_mirror, - N_("create a mirror repository (implies --bare)")), - OPT_BOOL('l', "local", &option_local, - N_("to clone from a local repository")), - OPT_BOOL(0, "no-hardlinks", &option_no_hardlinks, - N_("don't use local hardlinks, always copy")), - OPT_BOOL('s', "shared", &option_shared, - N_("setup as shared repository")), - { OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules, - N_("pathspec"), N_("initialize submodules in the clone"), - PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." }, - OPT_ALIAS(0, "recursive", "recurse-submodules"), - OPT_INTEGER('j', "jobs", &max_jobs, - N_("number of submodules cloned in parallel")), - OPT_STRING(0, "template", &option_template, N_("template-directory"), - N_("directory from which templates will be used")), - OPT_STRING_LIST(0, "reference", &option_required_reference, N_("repo"), - N_("reference repository")), - OPT_STRING_LIST(0, "reference-if-able", &option_optional_reference, - N_("repo"), N_("reference repository")), - OPT_BOOL(0, "dissociate", &option_dissociate, - N_("use --reference only while cloning")), - OPT_STRING('o', "origin", &option_origin, N_("name"), - N_("use <name> instead of 'origin' to track upstream")), - OPT_STRING('b', "branch", &option_branch, N_("branch"), - N_("checkout <branch> instead of the remote's HEAD")), - OPT_STRING('u', "upload-pack", &option_upload_pack, N_("path"), - N_("path to git-upload-pack on the remote")), - OPT_STRING(0, "depth", &option_depth, N_("depth"), - N_("create a shallow clone of that depth")), - OPT_STRING(0, "shallow-since", &option_since, N_("time"), - N_("create a shallow clone since a specific time")), - OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("ref"), - N_("deepen history of shallow clone, excluding ref")), - OPT_BOOL(0, "single-branch", &option_single_branch, - N_("clone only one branch, HEAD or --branch")), - OPT_BOOL(0, "no-tags", &option_no_tags, - N_("don't clone any tags, and make later fetches not to follow them")), - OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules, - N_("any cloned submodules will be shallow")), - OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"), - N_("separate git dir from working tree")), - OPT_STRING(0, "ref-format", &ref_format, N_("format"), - N_("specify the reference format to use")), - OPT_STRING_LIST('c', "config", &option_config, N_("key=value"), - N_("set config inside the new repository")), - OPT_STRING_LIST(0, "server-option", &server_options, - N_("server-specific"), N_("option to transmit")), - OPT_IPVERSION(&family), - OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options), - OPT_BOOL(0, "also-filter-submodules", &option_filter_submodules, - N_("apply partial clone filters to submodules")), - OPT_BOOL(0, "remote-submodules", &option_remote_submodules, - N_("any cloned submodules will use their remote-tracking branch")), - OPT_BOOL(0, "sparse", &option_sparse_checkout, - N_("initialize sparse-checkout file to include only files at root")), - OPT_STRING(0, "bundle-uri", &bundle_uri, - N_("uri"), N_("a URI for downloading bundles before fetching from origin remote")), - OPT_END() -}; - static const char *get_repo_path_1(struct strbuf *path, int *is_bundle) { static const char *suffix[] = { "/.git", "", ".git/.git", ".git" }; @@ -426,6 +342,8 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest, strbuf_setlen(src, src_len); die(_("failed to iterate over '%s'"), src->buf); } + + dir_iterator_free(iter); } static void clone_local(const char *src_repo, const char *dest_repo) @@ -521,51 +439,31 @@ static struct ref *find_remote_branch(const struct ref *refs, const char *branch return ref; } -static struct ref *wanted_peer_refs(const struct ref *refs, - struct refspec *refspec) +static struct ref *wanted_peer_refs(struct clone_opts *opts, + const struct ref *refs, + struct refspec *refspec) { - struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD")); - struct ref *local_refs = head; - struct ref **tail = head ? &head->next : &local_refs; - struct refspec_item tag_refspec; - - refspec_item_init(&tag_refspec, TAG_REFSPEC, 0); - - if (option_single_branch) { - struct ref *remote_head = NULL; - - if (!option_branch) - remote_head = guess_remote_head(head, refs, 0); - else { - free_one_ref(head); - local_refs = head = NULL; - tail = &local_refs; - remote_head = copy_ref(find_remote_branch(refs, option_branch)); - } - - if (!remote_head && option_branch) - warning(_("Could not find remote branch %s to clone."), - option_branch); - else { - int i; - for (i = 0; i < refspec->nr; i++) - get_fetch_map(remote_head, &refspec->items[i], - &tail, 0); - - /* if --branch=tag, pull the requested tag explicitly */ - get_fetch_map(remote_head, &tag_refspec, &tail, 0); - } - free_refs(remote_head); - } else { - int i; - for (i = 0; i < refspec->nr; i++) - get_fetch_map(refs, &refspec->items[i], &tail, 0); + struct ref *local_refs = NULL; + struct ref **tail = &local_refs; + struct ref *to_free = NULL; + + if (opts->wants_head) { + struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD")); + if (head) + tail_link_ref(head, &tail); + if (option_single_branch) + refs = to_free = guess_remote_head(head, refs, 0); + } else if (option_single_branch) { + local_refs = NULL; + tail = &local_refs; + refs = to_free = copy_ref(find_remote_branch(refs, option_branch)); } - if (!option_mirror && !option_single_branch && !option_no_tags) - get_fetch_map(refs, &tag_refspec, &tail, 0); + for (size_t i = 0; i < refspec->nr; i++) + get_fetch_map(refs, &refspec->items[i], &tail, 0); + + free_one_ref(to_free); - refspec_item_clear(&tag_refspec); return local_refs; } @@ -654,7 +552,7 @@ static void update_remote_refs(const struct ref *refs, if (refs) { write_remote_refs(mapped_refs); - if (option_single_branch && !option_no_tags) + if (option_single_branch && option_tags) write_followtags(refs, msg); } @@ -670,11 +568,11 @@ static void update_remote_refs(const struct ref *refs, } } -static void update_head(const struct ref *our, const struct ref *remote, +static void update_head(struct clone_opts *opts, const struct ref *our, const struct ref *remote, const char *unborn, const char *msg) { const char *head; - if (our && skip_prefix(our->name, "refs/heads/", &head)) { + if (our && !opts->detach && skip_prefix(our->name, "refs/heads/", &head)) { /* Local default branch link */ if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", our->name, NULL) < 0) die(_("unable to update HEAD")); @@ -685,8 +583,9 @@ static void update_head(const struct ref *our, const struct ref *remote, install_branch_config(0, head, remote_name, our->name); } } else if (our) { - struct commit *c = lookup_commit_reference(the_repository, - &our->old_oid); + struct commit *c = lookup_commit_or_die(&our->old_oid, + our->name); + /* --branch specifies a non-branch (i.e. tags), detach HEAD */ refs_update_ref(get_main_ref_store(the_repository), msg, "HEAD", &c->object.oid, NULL, REF_NO_DEREF, @@ -938,7 +837,7 @@ static void write_refspec_config(const char *src_ref_prefix, static void dissociate_from_references(void) { - char *alternates = git_pathdup("objects/info/alternates"); + char *alternates = repo_git_path(the_repository, "objects/info/alternates"); if (!access(alternates, F_OK)) { struct child_process cmd = CHILD_PROCESS_INIT; @@ -989,10 +888,108 @@ int cmd_clone(int argc, int hash_algo; enum ref_storage_format ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN; const int do_not_override_repo_unix_permissions = -1; + int option_reject_shallow = -1; /* unspecified */ + int deepen = 0; + char *option_template = NULL, *option_depth = NULL, *option_since = NULL; + char *option_origin = NULL; + struct string_list option_not = STRING_LIST_INIT_NODUP; + const char *real_git_dir = NULL; + const char *ref_format = NULL; + const char *option_upload_pack = "git-upload-pack"; + int option_progress = -1; + int option_sparse_checkout = 0; + enum transport_family family = TRANSPORT_FAMILY_ALL; + struct string_list option_config = STRING_LIST_INIT_DUP; + int option_dissociate = 0; + int option_filter_submodules = -1; /* unspecified */ + struct string_list server_options = STRING_LIST_INIT_NODUP; + const char *bundle_uri = NULL; + char *option_rev = NULL; + + struct clone_opts opts = CLONE_OPTS_INIT; struct transport_ls_refs_options transport_ls_refs_options = TRANSPORT_LS_REFS_OPTIONS_INIT; + struct option builtin_clone_options[] = { + OPT__VERBOSITY(&option_verbosity), + OPT_BOOL(0, "progress", &option_progress, + N_("force progress reporting")), + OPT_BOOL(0, "reject-shallow", &option_reject_shallow, + N_("don't clone shallow repository")), + OPT_BOOL('n', "no-checkout", &option_no_checkout, + N_("don't create a checkout")), + OPT_BOOL(0, "bare", &option_bare, N_("create a bare repository")), + OPT_HIDDEN_BOOL(0, "naked", &option_bare, + N_("create a bare repository")), + OPT_BOOL(0, "mirror", &option_mirror, + N_("create a mirror repository (implies --bare)")), + OPT_BOOL('l', "local", &option_local, + N_("to clone from a local repository")), + OPT_BOOL(0, "no-hardlinks", &option_no_hardlinks, + N_("don't use local hardlinks, always copy")), + OPT_BOOL('s', "shared", &option_shared, + N_("setup as shared repository")), + { OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules, + N_("pathspec"), N_("initialize submodules in the clone"), + PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." }, + OPT_ALIAS(0, "recursive", "recurse-submodules"), + OPT_INTEGER('j', "jobs", &max_jobs, + N_("number of submodules cloned in parallel")), + OPT_STRING(0, "template", &option_template, N_("template-directory"), + N_("directory from which templates will be used")), + OPT_STRING_LIST(0, "reference", &option_required_reference, N_("repo"), + N_("reference repository")), + OPT_STRING_LIST(0, "reference-if-able", &option_optional_reference, + N_("repo"), N_("reference repository")), + OPT_BOOL(0, "dissociate", &option_dissociate, + N_("use --reference only while cloning")), + OPT_STRING('o', "origin", &option_origin, N_("name"), + N_("use <name> instead of 'origin' to track upstream")), + OPT_STRING('b', "branch", &option_branch, N_("branch"), + N_("checkout <branch> instead of the remote's HEAD")), + OPT_STRING(0, "revision", &option_rev, N_("rev"), + N_("clone single revision <rev> and check out")), + OPT_STRING('u', "upload-pack", &option_upload_pack, N_("path"), + N_("path to git-upload-pack on the remote")), + OPT_STRING(0, "depth", &option_depth, N_("depth"), + N_("create a shallow clone of that depth")), + OPT_STRING(0, "shallow-since", &option_since, N_("time"), + N_("create a shallow clone since a specific time")), + OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("ref"), + N_("deepen history of shallow clone, excluding ref")), + OPT_BOOL(0, "single-branch", &option_single_branch, + N_("clone only one branch, HEAD or --branch")), + OPT_BOOL(0, "tags", &option_tags, + N_("clone tags, and make later fetches not to follow them")), + OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules, + N_("any cloned submodules will be shallow")), + OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"), + N_("separate git dir from working tree")), + OPT_STRING(0, "ref-format", &ref_format, N_("format"), + N_("specify the reference format to use")), + OPT_STRING_LIST('c', "config", &option_config, N_("key=value"), + N_("set config inside the new repository")), + OPT_STRING_LIST(0, "server-option", &server_options, + N_("server-specific"), N_("option to transmit")), + OPT_IPVERSION(&family), + OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options), + OPT_BOOL(0, "also-filter-submodules", &option_filter_submodules, + N_("apply partial clone filters to submodules")), + OPT_BOOL(0, "remote-submodules", &option_remote_submodules, + N_("any cloned submodules will use their remote-tracking branch")), + OPT_BOOL(0, "sparse", &option_sparse_checkout, + N_("initialize sparse-checkout file to include only files at root")), + OPT_STRING(0, "bundle-uri", &bundle_uri, + N_("uri"), N_("a URI for downloading bundles before fetching from origin remote")), + OPT_END() + }; + + const char * const builtin_clone_usage[] = { + N_("git clone [<options>] [--] <repo> [<dir>]"), + NULL + }; + packet_trace_identity("clone"); git_config(git_clone_config, NULL); @@ -1019,8 +1016,10 @@ int cmd_clone(int argc, die(_("unknown ref storage format '%s'"), ref_format); } - if (option_mirror) + if (option_mirror) { option_bare = 1; + option_tags = 0; + } if (option_bare) { if (real_git_dir) @@ -1138,8 +1137,8 @@ int cmd_clone(int argc, for_each_string_list_item(item, &option_recurse_submodules) { strbuf_addf(&sb, "submodule.active=%s", item->string); - string_list_append(&option_config, - strbuf_detach(&sb, NULL)); + string_list_append(&option_config, sb.buf); + strbuf_reset(&sb); } if (!git_config_get_bool("submodule.stickyRecursiveClone", &val) && @@ -1161,6 +1160,8 @@ int cmd_clone(int argc, string_list_append(&option_config, "submodule.alternateErrorStrategy=info"); } + + strbuf_release(&sb); } /* @@ -1220,7 +1221,7 @@ int cmd_clone(int argc, strbuf_reset(&buf); strbuf_addf(&buf, "%s/refs", git_dir); - safe_create_dir(buf.buf, 1); + safe_create_dir(the_repository, buf.buf, 1); /* * additional config can be injected with -c, make sure it's included @@ -1285,7 +1286,7 @@ int cmd_clone(int argc, strbuf_addstr(&branch_top, src_ref_prefix); git_config_set("core.bare", "true"); - } else { + } else if (!option_rev) { strbuf_addf(&branch_top, "refs/remotes/%s/", remote_name); } @@ -1293,7 +1294,7 @@ int cmd_clone(int argc, git_config_set(key.buf, repo); strbuf_reset(&key); - if (option_no_tags) { + if (!option_tags) { strbuf_addf(&key, "remote.%s.tagOpt", remote_name); git_config_set(key.buf, "--no-tags"); strbuf_reset(&key); @@ -1304,8 +1305,9 @@ int cmd_clone(int argc, remote = remote_get_early(remote_name); - refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix, - branch_top.buf); + if (!option_rev) + refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix, + branch_top.buf); path = get_repo_path(remote->url.v[0], &is_bundle); is_local = option_local != 0 && path && !is_bundle; @@ -1348,6 +1350,11 @@ int cmd_clone(int argc, transport_set_option(transport, TRANS_OPT_KEEP, "yes"); + die_for_incompatible_opt2(!!option_rev, "--revision", + !!option_branch, "--branch"); + die_for_incompatible_opt2(!!option_rev, "--revision", + option_mirror, "--mirror"); + if (reject_shallow) transport_set_option(transport, TRANS_OPT_REJECT_SHALLOW, "1"); if (option_depth) @@ -1359,9 +1366,13 @@ int cmd_clone(int argc, if (option_not.nr) transport_set_option(transport, TRANS_OPT_DEEPEN_NOT, (const char *)&option_not); - if (option_single_branch) + if (option_single_branch) { transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1"); + if (option_branch) + opts.wants_head = 0; + } + if (option_upload_pack) transport_set_option(transport, TRANS_OPT_UPLOADPACK, option_upload_pack); @@ -1380,15 +1391,38 @@ int cmd_clone(int argc, if (transport->smart_options && !deepen && !filter_options.choice) transport->smart_options->check_self_contained_and_connected = 1; - strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD"); + if (option_rev) { + option_tags = 0; + option_single_branch = 0; + opts.wants_head = 0; + opts.detach = 1; + + refspec_append(&remote->fetch, option_rev); + } + + if (option_tags || option_branch) + /* + * Add tags refspec when user asked for tags (implicitly) or + * specified --branch, whose argument might be a tag. + */ + refspec_append(&remote->fetch, TAG_REFSPEC); + refspec_ref_prefixes(&remote->fetch, &transport_ls_refs_options.ref_prefixes); if (option_branch) expand_ref_prefix(&transport_ls_refs_options.ref_prefixes, option_branch); - if (!option_no_tags) - strvec_push(&transport_ls_refs_options.ref_prefixes, - "refs/tags/"); + + /* + * As part of transport_get_remote_refs() the server tells us the hash + * algorithm, which we require to initialize the repo. But calling that + * function without any ref prefix, will cause the server to announce + * all known refs. If the argument passed to --revision was a hex oid, + * ref_prefixes will be empty so we fall back to asking about HEAD to + * reduce traffic from the server. + */ + if (opts.wants_head || transport_ls_refs_options.ref_prefixes.nr == 0) + strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD"); refs = transport_get_remote_refs(transport, &transport_ls_refs_options); @@ -1465,7 +1499,7 @@ int cmd_clone(int argc, } if (refs) - mapped_refs = wanted_peer_refs(refs, &remote->fetch); + mapped_refs = wanted_peer_refs(&opts, refs, &remote->fetch); if (mapped_refs) { /* @@ -1498,6 +1532,11 @@ int cmd_clone(int argc, if (!our_head_points_at) die(_("Remote branch %s not found in upstream %s"), option_branch, remote_name); + } else if (option_rev) { + our_head_points_at = mapped_refs; + if (!our_head_points_at) + die(_("Remote revision %s not found in upstream %s"), + option_rev, remote_name); } else if (remote_head_points_at) { our_head_points_at = remote_head_points_at; } else if (remote_head) { @@ -1536,8 +1575,9 @@ int cmd_clone(int argc, free(to_free); } - write_refspec_config(src_ref_prefix, our_head_points_at, - remote_head_points_at, &branch_top); + if (!option_rev) + write_refspec_config(src_ref_prefix, our_head_points_at, + remote_head_points_at, &branch_top); if (filter_options.choice) partial_clone_register(remote_name, &filter_options); @@ -1553,7 +1593,7 @@ int cmd_clone(int argc, branch_top.buf, reflog_msg.buf, transport, !is_local); - update_head(our_head_points_at, remote_head, unborn_head, reflog_msg.buf); + update_head(&opts, our_head_points_at, remote_head, unborn_head, reflog_msg.buf); /* * We want to show progress for recursive submodule clones iff @@ -1578,6 +1618,10 @@ int cmd_clone(int argc, err = checkout(submodule_progress, filter_submodules, ref_storage_format); + string_list_clear(&option_not, 0); + string_list_clear(&option_config, 0); + string_list_clear(&server_options, 0); + free(remote_name); strbuf_release(&reflog_msg); strbuf_release(&branch_top); diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index bd70d052e7..8ca75262c5 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -305,6 +305,7 @@ static int graph_write(int argc, const char **argv, const char *prefix, oidset_init(&commits, 0); if (opts.progress) progress = start_delayed_progress( + the_repository, _("Collecting commits from input"), 0); while (strbuf_getline(&buf, stdin) != EOF) { diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index 2ca1a57ebb..38457600a4 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -119,8 +119,8 @@ int cmd_commit_tree(int argc, git_config(git_default_config, NULL); - if (argc < 2 || !strcmp(argv[1], "-h")) - usage_with_options(commit_tree_usage, options); + show_usage_with_options_if_asked(argc, argv, + commit_tree_usage, options); argc = parse_options(argc, argv, prefix, options, commit_tree_usage, 0); diff --git a/builtin/commit.c b/builtin/commit.c index ef5e622c07..2f45968222 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -44,7 +44,7 @@ #include "trailer.h" static const char * const builtin_commit_usage[] = { - N_("git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" + N_("git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" @@ -352,6 +352,7 @@ static const char *prepare_index(const char **argv, const char *prefix, struct pathspec pathspec; int refresh_flags = REFRESH_QUIET; const char *ret; + char *path = NULL; if (is_status) refresh_flags |= REFRESH_UNMERGED; @@ -524,9 +525,9 @@ static const char *prepare_index(const char **argv, const char *prefix, if (write_locked_index(the_repository->index, &index_lock, 0)) die(_("unable to write new index file")); - hold_lock_file_for_update(&false_lock, - git_path("next-index-%"PRIuMAX, - (uintmax_t) getpid()), + path = repo_git_path(the_repository, "next-index-%"PRIuMAX, + (uintmax_t) getpid()); + hold_lock_file_for_update(&false_lock, path, LOCK_DIE_ON_ERROR); create_base_index(current_head); @@ -542,6 +543,7 @@ static const char *prepare_index(const char **argv, const char *prefix, out: string_list_clear(&partial, 0); clear_pathspec(&pathspec); + free(path); return ret; } @@ -1559,8 +1561,8 @@ struct repository *repo UNUSED) OPT_END(), }; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_status_usage, builtin_status_options); + show_usage_with_options_if_asked(argc, argv, + builtin_status_usage, builtin_status_options); prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; @@ -1736,8 +1738,8 @@ int cmd_commit(int argc, struct strbuf err = STRBUF_INIT; int ret = 0; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_commit_usage, builtin_commit_options); + show_usage_with_options_if_asked(argc, argv, + builtin_commit_usage, builtin_commit_options); prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; diff --git a/builtin/config.c b/builtin/config.c index 16e6e30555..53a90094e3 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -775,13 +775,13 @@ static void location_options_init(struct config_location_options *opts, opts->source.file = opts->file_to_free = git_system_config(); opts->source.scope = CONFIG_SCOPE_SYSTEM; } else if (opts->use_local_config) { - opts->source.file = opts->file_to_free = git_pathdup("config"); + opts->source.file = opts->file_to_free = repo_git_path(the_repository, "config"); opts->source.scope = CONFIG_SCOPE_LOCAL; } else if (opts->use_worktree_config) { struct worktree **worktrees = get_worktrees(); if (the_repository->repository_format_worktree_config) opts->source.file = opts->file_to_free = - git_pathdup("config.worktree"); + repo_git_path(the_repository, "config.worktree"); else if (worktrees[0] && worktrees[1]) die(_("--worktree cannot be used with multiple " "working trees unless the config\n" @@ -790,7 +790,7 @@ static void location_options_init(struct config_location_options *opts, "section in \"git help worktree\" for details")); else opts->source.file = opts->file_to_free = - git_pathdup("config"); + repo_git_path(the_repository, "config"); opts->source.scope = CONFIG_SCOPE_LOCAL; free_worktrees(worktrees); } else if (opts->source.file) { @@ -1087,7 +1087,7 @@ static int show_editor(struct config_location_options *opts) git_config(git_default_config, NULL); config_file = opts->source.file ? xstrdup(opts->source.file) : - git_pathdup("config"); + repo_git_path(the_repository, "config"); if (opts->use_global_config) { int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666); if (fd >= 0) { diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c index bc22f5c6d2..e707618e74 100644 --- a/builtin/credential-cache--daemon.c +++ b/builtin/credential-cache--daemon.c @@ -142,9 +142,9 @@ static void serve_one_client(FILE *in, FILE *out) fprintf(out, "username=%s\n", e->item.username); if (e->item.password) fprintf(out, "password=%s\n", e->item.password); - if (credential_has_capability(&c.capa_authtype, CREDENTIAL_OP_HELPER) && e->item.authtype) + if (credential_has_capability(&c.capa_authtype, CREDENTIAL_OP_RESPONSE) && e->item.authtype) fprintf(out, "authtype=%s\n", e->item.authtype); - if (credential_has_capability(&c.capa_authtype, CREDENTIAL_OP_HELPER) && e->item.credential) + if (credential_has_capability(&c.capa_authtype, CREDENTIAL_OP_RESPONSE) && e->item.credential) fprintf(out, "credential=%s\n", e->item.credential); if (e->item.password_expiry_utc != TIME_MAX) fprintf(out, "password_expiry_utc=%"PRItime"\n", diff --git a/builtin/credential.c b/builtin/credential.c index 14c8c6608b..2e11b15dde 100644 --- a/builtin/credential.c +++ b/builtin/credential.c @@ -18,7 +18,8 @@ int cmd_credential(int argc, git_config(git_default_config, NULL); - if (argc != 2 || !strcmp(argv[1], "-h")) + show_usage_if_asked(argc, argv, usage_msg); + if (argc != 2) usage(usage_msg); op = argv[1]; @@ -32,15 +33,15 @@ int cmd_credential(int argc, die("unable to read credential from stdin"); if (!strcmp(op, "fill")) { - credential_fill(&c, 0); + credential_fill(the_repository, &c, 0); credential_next_state(&c); credential_write(&c, stdout, CREDENTIAL_OP_RESPONSE); } else if (!strcmp(op, "approve")) { credential_set_all_capabilities(&c, CREDENTIAL_OP_HELPER); - credential_approve(&c); + credential_approve(the_repository, &c); } else if (!strcmp(op, "reject")) { credential_set_all_capabilities(&c, CREDENTIAL_OP_HELPER); - credential_reject(&c); + credential_reject(the_repository, &c); } else { usage(usage_msg); } diff --git a/builtin/diagnose.c b/builtin/diagnose.c index 66a22d918e..33c39bd598 100644 --- a/builtin/diagnose.c +++ b/builtin/diagnose.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "builtin.h" #include "abspath.h" #include "gettext.h" @@ -58,7 +60,7 @@ int cmd_diagnose(int argc, } /* Prepare diagnostics */ - if (create_diagnostics_archive(&zip_path, mode)) + if (create_diagnostics_archive(the_repository, &zip_path, mode)) die_errno(_("unable to create diagnostics archive %s"), zip_path.buf); diff --git a/builtin/diff-files.c b/builtin/diff-files.c index 604b04bb2c..99b1749723 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -29,8 +29,7 @@ int cmd_diff_files(int argc, int result; unsigned options = 0; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage(diff_files_usage); + show_usage_if_asked(argc, argv, diff_files_usage); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ diff --git a/builtin/diff-index.c b/builtin/diff-index.c index ebc824602e..81c0bc8ed7 100644 --- a/builtin/diff-index.c +++ b/builtin/diff-index.c @@ -26,8 +26,7 @@ int cmd_diff_index(int argc, int i; int result; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage(diff_cache_usage); + show_usage_if_asked(argc, argv, diff_cache_usage); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ diff --git a/builtin/diff-pairs.c b/builtin/diff-pairs.c new file mode 100644 index 0000000000..71c045331a --- /dev/null +++ b/builtin/diff-pairs.c @@ -0,0 +1,207 @@ +#include "builtin.h" +#include "config.h" +#include "diff.h" +#include "diffcore.h" +#include "gettext.h" +#include "hash.h" +#include "hex.h" +#include "object.h" +#include "parse-options.h" +#include "revision.h" +#include "strbuf.h" + +static unsigned parse_mode_or_die(const char *mode, const char **end) +{ + uint16_t ret; + + *end = parse_mode(mode, &ret); + if (!*end) + die(_("unable to parse mode: %s"), mode); + return ret; +} + +static void parse_oid_or_die(const char *hex, struct object_id *oid, + const char **end, const struct git_hash_algo *algop) +{ + if (parse_oid_hex_algop(hex, oid, end, algop) || *(*end)++ != ' ') + die(_("unable to parse object id: %s"), hex); +} + +int cmd_diff_pairs(int argc, const char **argv, const char *prefix, + struct repository *repo) +{ + struct strbuf path_dst = STRBUF_INIT; + struct strbuf path = STRBUF_INIT; + struct strbuf meta = STRBUF_INIT; + struct option *parseopts; + struct rev_info revs; + int line_term = '\0'; + int ret; + + const char * const builtin_diff_pairs_usage[] = { + N_("git diff-pairs -z [<diff-options>]"), + NULL + }; + struct option builtin_diff_pairs_options[] = { + OPT_END() + }; + + repo_init_revisions(repo, &revs, prefix); + + /* + * Diff options are usually parsed implicitly as part of + * setup_revisions(). Explicitly handle parsing to ensure options are + * printed in the usage message. + */ + parseopts = add_diff_options(builtin_diff_pairs_options, &revs.diffopt); + show_usage_with_options_if_asked(argc, argv, builtin_diff_pairs_usage, parseopts); + + repo_config(repo, git_diff_basic_config, NULL); + revs.diffopt.no_free = 1; + revs.disable_stdin = 1; + revs.abbrev = 0; + revs.diff = 1; + + argc = parse_options(argc, argv, prefix, parseopts, builtin_diff_pairs_usage, + PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_DASHDASH); + + if (setup_revisions(argc, argv, &revs, NULL) > 1) + usagef(_("unrecognized argument: %s"), argv[0]); + + /* + * With the -z option, both command input and raw output are + * NUL-delimited (this mode does not affect patch output). At present + * only NUL-delimited raw diff formatted input is supported. + */ + if (revs.diffopt.line_termination) + usage(_("working without -z is not supported")); + + if (revs.prune_data.nr) + usage(_("pathspec arguments not supported")); + + if (revs.pending.nr || revs.max_count != -1 || + revs.min_age != (timestamp_t)-1 || + revs.max_age != (timestamp_t)-1) + usage(_("revision arguments not allowed")); + + if (!revs.diffopt.output_format) + revs.diffopt.output_format = DIFF_FORMAT_PATCH; + + /* + * If rename detection is not requested, use rename information from the + * raw diff formatted input. Setting skip_resolving_statuses ensures + * diffcore_std() does not mess with rename information already present + * in queued filepairs. + */ + if (!revs.diffopt.detect_rename) + revs.diffopt.skip_resolving_statuses = 1; + + while (1) { + struct object_id oid_a, oid_b; + struct diff_filepair *pair; + unsigned mode_a, mode_b; + const char *p; + char status; + + if (strbuf_getwholeline(&meta, stdin, line_term) == EOF) + break; + + p = meta.buf; + if (!*p) { + diffcore_std(&revs.diffopt); + diff_flush(&revs.diffopt); + /* + * When the diff queue is explicitly flushed, append a + * NUL byte to separate batches of diffs. + */ + fputc('\0', revs.diffopt.file); + fflush(revs.diffopt.file); + continue; + } + + if (*p != ':') + die(_("invalid raw diff input")); + p++; + + mode_a = parse_mode_or_die(p, &p); + mode_b = parse_mode_or_die(p, &p); + + if (S_ISDIR(mode_a) || S_ISDIR(mode_b)) + die(_("tree objects not supported")); + + parse_oid_or_die(p, &oid_a, &p, repo->hash_algo); + parse_oid_or_die(p, &oid_b, &p, repo->hash_algo); + + status = *p++; + + if (strbuf_getwholeline(&path, stdin, line_term) == EOF) + die(_("got EOF while reading path")); + + switch (status) { + case DIFF_STATUS_ADDED: + pair = diff_queue_addremove(&diff_queued_diff, + &revs.diffopt, '+', mode_b, + &oid_b, 1, path.buf, 0); + if (pair) + pair->status = status; + break; + + case DIFF_STATUS_DELETED: + pair = diff_queue_addremove(&diff_queued_diff, + &revs.diffopt, '-', mode_a, + &oid_a, 1, path.buf, 0); + if (pair) + pair->status = status; + break; + + case DIFF_STATUS_TYPE_CHANGED: + case DIFF_STATUS_MODIFIED: + pair = diff_queue_change(&diff_queued_diff, &revs.diffopt, + mode_a, mode_b, &oid_a, &oid_b, + 1, 1, path.buf, 0, 0); + if (pair) + pair->status = status; + break; + + case DIFF_STATUS_RENAMED: + case DIFF_STATUS_COPIED: { + struct diff_filespec *a, *b; + unsigned int score; + + if (strbuf_getwholeline(&path_dst, stdin, line_term) == EOF) + die(_("got EOF while reading destination path")); + + a = alloc_filespec(path.buf); + b = alloc_filespec(path_dst.buf); + fill_filespec(a, &oid_a, 1, mode_a); + fill_filespec(b, &oid_b, 1, mode_b); + + pair = diff_queue(&diff_queued_diff, a, b); + + if (strtoul_ui(p, 10, &score)) + die(_("unable to parse rename/copy score: %s"), p); + + pair->score = score * MAX_SCORE / 100; + pair->status = status; + pair->renamed_pair = 1; + } + break; + + default: + die(_("unknown diff status: %c"), status); + } + } + + revs.diffopt.no_free = 0; + diffcore_std(&revs.diffopt); + diff_flush(&revs.diffopt); + ret = diff_result_code(&revs); + + strbuf_release(&path_dst); + strbuf_release(&path); + strbuf_release(&meta); + release_revisions(&revs); + FREE_AND_NULL(parseopts); + + return ret; +} diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 40804e7b48..e31cc797fe 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -122,8 +122,7 @@ int cmd_diff_tree(int argc, int read_stdin = 0; int merge_base = 0; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage(diff_tree_usage); + show_usage_if_asked(argc, argv, diff_tree_usage); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ diff --git a/builtin/difftool.c b/builtin/difftool.c index 03a8bb92a9..41cd00066c 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -12,8 +12,6 @@ * Copyright (C) 2016 Johannes Schindelin */ -#define USE_THE_REPOSITORY_VARIABLE - #include "builtin.h" #include "abspath.h" @@ -36,18 +34,27 @@ #include "entry.h" #include "setup.h" -static int trust_exit_code; - static const char *const builtin_difftool_usage[] = { N_("git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]"), NULL }; +struct difftool_options { + int has_symlinks; + int symlinks; + int trust_exit_code; +}; + static int difftool_config(const char *var, const char *value, const struct config_context *ctx, void *cb) { + struct difftool_options *dt_options = (struct difftool_options *)cb; if (!strcmp(var, "difftool.trustexitcode")) { - trust_exit_code = git_config_bool(var, value); + dt_options->trust_exit_code = git_config_bool(var, value); + return 0; + } + if (!strcmp(var, "core.symlinks")) { + dt_options->has_symlinks = git_config_bool(var, value); return 0; } @@ -63,7 +70,8 @@ static int print_tool_help(void) return run_command(&cmd); } -static int parse_index_info(char *p, int *mode1, int *mode2, +static int parse_index_info(struct repository *repo, + char *p, int *mode1, int *mode2, struct object_id *oid1, struct object_id *oid2, char *status) { @@ -75,11 +83,11 @@ static int parse_index_info(char *p, int *mode1, int *mode2, *mode2 = (int)strtol(p + 1, &p, 8); if (*p != ' ') return error("expected ' ', got '%c'", *p); - if (parse_oid_hex(++p, oid1, (const char **)&p)) + if (parse_oid_hex_algop(++p, oid1, (const char **)&p, repo->hash_algo)) return error("expected object ID, got '%s'", p); if (*p != ' ') return error("expected ' ', got '%c'", *p); - if (parse_oid_hex(++p, oid2, (const char **)&p)) + if (parse_oid_hex_algop(++p, oid2, (const char **)&p, repo->hash_algo)) return error("expected object ID, got '%s'", p); if (*p != ' ') return error("expected ' ', got '%c'", *p); @@ -106,7 +114,8 @@ static void add_path(struct strbuf *buf, size_t base_len, const char *path) /* * Determine whether we can simply reuse the file in the worktree. */ -static int use_wt_file(const char *workdir, const char *name, +static int use_wt_file(struct repository *repo, + const char *workdir, const char *name, struct object_id *oid) { struct strbuf buf = STRBUF_INIT; @@ -121,7 +130,7 @@ static int use_wt_file(const char *workdir, const char *name, int fd = open(buf.buf, O_RDONLY); if (fd >= 0 && - !index_fd(the_repository->index, &wt_oid, fd, &st, OBJ_BLOB, name, 0)) { + !index_fd(repo->index, &wt_oid, fd, &st, OBJ_BLOB, name, 0)) { if (is_null_oid(oid)) { oidcpy(oid, &wt_oid); use = 1; @@ -212,13 +221,14 @@ static int path_entry_cmp(const void *cmp_data UNUSED, return strcmp(a->path, key ? key : b->path); } -static void changed_files(struct hashmap *result, const char *index_path, +static void changed_files(struct repository *repo, + struct hashmap *result, const char *index_path, const char *workdir) { struct child_process update_index = CHILD_PROCESS_INIT; struct child_process diff_files = CHILD_PROCESS_INIT; struct strbuf buf = STRBUF_INIT; - const char *git_dir = absolute_path(repo_get_git_dir(the_repository)); + const char *git_dir = absolute_path(repo_get_git_dir(repo)); FILE *fp; strvec_pushl(&update_index.args, @@ -291,13 +301,15 @@ static int ensure_leading_directories(char *path) * to compare the readlink(2) result as text, even on a filesystem that is * capable of doing a symbolic link. */ -static char *get_symlink(const struct object_id *oid, const char *path) +static char *get_symlink(struct repository *repo, + struct difftool_options *dt_options, + const struct object_id *oid, const char *path) { char *data; if (is_null_oid(oid)) { /* The symlink is unknown to Git so read from the filesystem */ struct strbuf link = STRBUF_INIT; - if (has_symlinks) { + if (dt_options->has_symlinks) { if (strbuf_readlink(&link, path, strlen(path))) die(_("could not read symlink %s"), path); } else if (strbuf_read_file(&link, path, 128)) @@ -307,8 +319,7 @@ static char *get_symlink(const struct object_id *oid, const char *path) } else { enum object_type type; unsigned long size; - data = repo_read_object_file(the_repository, oid, &type, - &size); + data = repo_read_object_file(repo, oid, &type, &size); if (!data) die(_("could not read object %s for symlink %s"), oid_to_hex(oid), path); @@ -355,7 +366,9 @@ static void write_standin_files(struct pair_entry *entry, write_file_in_directory(rdir, rdir_len, entry->path, entry->right); } -static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, +static int run_dir_diff(struct repository *repo, + struct difftool_options *dt_options, + const char *extcmd, const char *prefix, struct child_process *child) { struct strbuf info = STRBUF_INIT, lpath = STRBUF_INIT; @@ -375,7 +388,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, struct hashmap symlinks2 = HASHMAP_INIT(pair_cmp, NULL); struct hashmap_iter iter; struct pair_entry *entry; - struct index_state wtindex = INDEX_STATE_INIT(the_repository); + struct index_state wtindex = INDEX_STATE_INIT(repo); struct checkout lstate, rstate; int err = 0; struct child_process cmd = CHILD_PROCESS_INIT; @@ -383,7 +396,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, struct hashmap tmp_modified = HASHMAP_INIT(path_entry_cmp, NULL); int indices_loaded = 0; - workdir = repo_get_work_tree(the_repository); + workdir = repo_get_work_tree(repo); /* Setup temp directories */ tmp = getenv("TMPDIR"); @@ -438,8 +451,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, "not supported in\n" "directory diff mode ('-d' and '--dir-diff').")); - if (parse_index_info(info.buf, &lmode, &rmode, &loid, &roid, - &status)) + if (parse_index_info(repo, info.buf, &lmode, &rmode, &loid, &roid, &status)) break; if (strbuf_getline_nul(&lpath, fp)) break; @@ -469,13 +481,13 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, } if (S_ISLNK(lmode)) { - char *content = get_symlink(&loid, src_path); + char *content = get_symlink(repo, dt_options, &loid, src_path); add_left_or_right(&symlinks2, src_path, content, 0); free(content); } if (S_ISLNK(rmode)) { - char *content = get_symlink(&roid, dst_path); + char *content = get_symlink(repo, dt_options, &roid, dst_path); add_left_or_right(&symlinks2, dst_path, content, 1); free(content); } @@ -500,7 +512,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, } hashmap_add(&working_tree_dups, &entry->entry); - if (!use_wt_file(workdir, dst_path, &roid)) { + if (!use_wt_file(repo, workdir, dst_path, &roid)) { if (checkout_path(rmode, &roid, dst_path, &rstate)) { ret = error("could not write '%s'", @@ -528,7 +540,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, goto finish; } add_path(&wtdir, wtdir_len, dst_path); - if (symlinks) { + if (dt_options->symlinks) { if (symlink(wtdir.buf, rdir.buf)) { ret = error_errno("could not symlink '%s' to '%s'", wtdir.buf, rdir.buf); goto finish; @@ -614,7 +626,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, if (lstat(rdir.buf, &st)) continue; - if ((symlinks && S_ISLNK(st.st_mode)) || !S_ISREG(st.st_mode)) + if ((dt_options->symlinks && S_ISLNK(st.st_mode)) || !S_ISREG(st.st_mode)) continue; if (!indices_loaded) { @@ -626,9 +638,9 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, ret = error("could not write %s", buf.buf); goto finish; } - changed_files(&wt_modified, buf.buf, workdir); + changed_files(repo, &wt_modified, buf.buf, workdir); strbuf_setlen(&rdir, rdir_len); - changed_files(&tmp_modified, buf.buf, rdir.buf); + changed_files(repo, &tmp_modified, buf.buf, rdir.buf); add_path(&rdir, rdir_len, name); indices_loaded = 1; } @@ -702,11 +714,15 @@ static int run_file_diff(int prompt, const char *prefix, int cmd_difftool(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { - int use_gui_tool = -1, dir_diff = 0, prompt = -1, symlinks = 0, - tool_help = 0, no_index = 0; + int use_gui_tool = -1, dir_diff = 0, prompt = -1, tool_help = 0, no_index = 0; static char *difftool_cmd = NULL, *extcmd = NULL; + struct difftool_options dt_options = { + .has_symlinks = 1, + .symlinks = 1, + .trust_exit_code = 0 + }; struct option builtin_difftool_options[] = { OPT_BOOL('g', "gui", &use_gui_tool, N_("use `diff.guitool` instead of `diff.tool`")), @@ -717,14 +733,14 @@ int cmd_difftool(int argc, 0, PARSE_OPT_NONEG), OPT_SET_INT_F(0, "prompt", &prompt, NULL, 1, PARSE_OPT_NONEG | PARSE_OPT_HIDDEN), - OPT_BOOL(0, "symlinks", &symlinks, + OPT_BOOL(0, "symlinks", &dt_options.symlinks, N_("use symlinks in dir-diff mode")), OPT_STRING('t', "tool", &difftool_cmd, N_("tool"), N_("use the specified diff tool")), OPT_BOOL(0, "tool-help", &tool_help, N_("print a list of diff tools that may be used with " "`--tool`")), - OPT_BOOL(0, "trust-exit-code", &trust_exit_code, + OPT_BOOL(0, "trust-exit-code", &dt_options.trust_exit_code, N_("make 'git-difftool' exit when an invoked diff " "tool returns a non-zero exit code")), OPT_STRING('x', "extcmd", &extcmd, N_("command"), @@ -734,8 +750,9 @@ int cmd_difftool(int argc, }; struct child_process child = CHILD_PROCESS_INIT; - git_config(difftool_config, NULL); - symlinks = has_symlinks; + if (repo) + repo_config(repo, difftool_config, &dt_options); + dt_options.symlinks = dt_options.has_symlinks; argc = parse_options(argc, argv, prefix, builtin_difftool_options, builtin_difftool_usage, PARSE_OPT_KEEP_UNKNOWN_OPT | @@ -749,8 +766,8 @@ int cmd_difftool(int argc, if (!no_index){ setup_work_tree(); - setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1); - setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(the_repository)), 1); + setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(repo)), 1); + setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(repo)), 1); } else if (dir_diff) die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index"); @@ -783,7 +800,7 @@ int cmd_difftool(int argc, } setenv("GIT_DIFFTOOL_TRUST_EXIT_CODE", - trust_exit_code ? "true" : "false", 1); + dt_options.trust_exit_code ? "true" : "false", 1); /* * In directory diff mode, 'git-difftool--helper' is called once @@ -799,6 +816,6 @@ int cmd_difftool(int argc, strvec_pushv(&child.args, argv); if (dir_diff) - return run_dir_diff(extcmd, symlinks, prefix, &child); + return run_dir_diff(repo, &dt_options, extcmd, prefix, &child); return run_file_diff(prompt, prefix, &child); } diff --git a/builtin/fast-export.c b/builtin/fast-export.c index a5c82eef1d..126980f724 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -35,8 +35,11 @@ static const char *fast_export_usage[] = { NULL }; +enum sign_mode { SIGN_ABORT, SIGN_VERBATIM, SIGN_STRIP, SIGN_WARN_VERBATIM, SIGN_WARN_STRIP }; + static int progress; -static enum signed_tag_mode { SIGNED_TAG_ABORT, VERBATIM, WARN, WARN_STRIP, STRIP } signed_tag_mode = SIGNED_TAG_ABORT; +static enum sign_mode signed_tag_mode = SIGN_ABORT; +static enum sign_mode signed_commit_mode = SIGN_ABORT; static enum tag_of_filtered_mode { TAG_FILTERING_ABORT, DROP, REWRITE } tag_of_filtered_mode = TAG_FILTERING_ABORT; static enum reencode_mode { REENCODE_ABORT, REENCODE_YES, REENCODE_NO } reencode_mode = REENCODE_ABORT; static int fake_missing_tagger; @@ -53,23 +56,24 @@ static int anonymize; static struct hashmap anonymized_seeds; static struct revision_sources revision_sources; -static int parse_opt_signed_tag_mode(const struct option *opt, +static int parse_opt_sign_mode(const struct option *opt, const char *arg, int unset) { - enum signed_tag_mode *val = opt->value; - - if (unset || !strcmp(arg, "abort")) - *val = SIGNED_TAG_ABORT; + enum sign_mode *val = opt->value; + if (unset) + return 0; + else if (!strcmp(arg, "abort")) + *val = SIGN_ABORT; else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore")) - *val = VERBATIM; - else if (!strcmp(arg, "warn")) - *val = WARN; + *val = SIGN_VERBATIM; + else if (!strcmp(arg, "warn-verbatim") || !strcmp(arg, "warn")) + *val = SIGN_WARN_VERBATIM; else if (!strcmp(arg, "warn-strip")) - *val = WARN_STRIP; + *val = SIGN_WARN_STRIP; else if (!strcmp(arg, "strip")) - *val = STRIP; + *val = SIGN_STRIP; else - return error("Unknown signed-tags mode: %s", arg); + return error("Unknown %s mode: %s", opt->long_name, arg); return 0; } @@ -510,21 +514,6 @@ static void show_filemodify(struct diff_queue_struct *q, } } -static const char *find_encoding(const char *begin, const char *end) -{ - const char *needle = "\nencoding "; - char *bol, *eol; - - bol = memmem(begin, end ? end - begin : strlen(begin), - needle, strlen(needle)); - if (!bol) - return NULL; - bol += strlen(needle); - eol = strchrnul(bol, '\n'); - *eol = '\0'; - return bol; -} - static char *anonymize_ref_component(void) { static int counter; @@ -626,13 +615,53 @@ static void anonymize_ident_line(const char **beg, const char **end) *end = out->buf + out->len; } +/* + * find_commit_multiline_header is similar to find_commit_header, + * except that it handles multi-line headers, rather than simply + * returning the first line of the header. + * + * The returned string has had the ' ' line continuation markers + * removed, and points to allocated memory that must be free()d (not + * to memory within 'msg'). + * + * If the header is found, then *end is set to point at the '\n' in + * msg that immediately follows the header value. + */ +static const char *find_commit_multiline_header(const char *msg, + const char *key, + const char **end) +{ + struct strbuf val = STRBUF_INIT; + const char *bol, *eol; + size_t len; + + bol = find_commit_header(msg, key, &len); + if (!bol) + return NULL; + eol = bol + len; + strbuf_add(&val, bol, len); + + while (eol[0] == '\n' && eol[1] == ' ') { + bol = eol + 2; + eol = strchrnul(bol, '\n'); + strbuf_addch(&val, '\n'); + strbuf_add(&val, bol, eol - bol); + } + + *end = eol; + return strbuf_detach(&val, NULL); +} + static void handle_commit(struct commit *commit, struct rev_info *rev, struct string_list *paths_of_changed_objects) { int saved_output_format = rev->diffopt.output_format; - const char *commit_buffer; + const char *commit_buffer, *commit_buffer_cursor; const char *author, *author_end, *committer, *committer_end; - const char *encoding, *message; + const char *encoding = NULL; + size_t encoding_len; + const char *signature_alg = NULL, *signature = NULL; + const char *message; char *reencoded = NULL; struct commit_list *p; const char *refname; @@ -641,21 +670,43 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, rev->diffopt.output_format = DIFF_FORMAT_CALLBACK; parse_commit_or_die(commit); - commit_buffer = repo_get_commit_buffer(the_repository, commit, NULL); - author = strstr(commit_buffer, "\nauthor "); + commit_buffer_cursor = commit_buffer = repo_get_commit_buffer(the_repository, commit, NULL); + + author = strstr(commit_buffer_cursor, "\nauthor "); if (!author) die("could not find author in commit %s", oid_to_hex(&commit->object.oid)); author++; - author_end = strchrnul(author, '\n'); - committer = strstr(author_end, "\ncommitter "); + commit_buffer_cursor = author_end = strchrnul(author, '\n'); + + committer = strstr(commit_buffer_cursor, "\ncommitter "); if (!committer) die("could not find committer in commit %s", oid_to_hex(&commit->object.oid)); committer++; - committer_end = strchrnul(committer, '\n'); - message = strstr(committer_end, "\n\n"); - encoding = find_encoding(committer_end, message); + commit_buffer_cursor = committer_end = strchrnul(committer, '\n'); + + /* + * find_commit_header() and find_commit_multiline_header() get + * a `+ 1` because commit_buffer_cursor points at the trailing + * "\n" at the end of the previous line, but they want a + * pointer to the beginning of the next line. + */ + + if (*commit_buffer_cursor == '\n') { + encoding = find_commit_header(commit_buffer_cursor + 1, "encoding", &encoding_len); + if (encoding) + commit_buffer_cursor = encoding + encoding_len; + } + + if (*commit_buffer_cursor == '\n') { + if ((signature = find_commit_multiline_header(commit_buffer_cursor + 1, "gpgsig", &commit_buffer_cursor))) + signature_alg = "sha1"; + else if ((signature = find_commit_multiline_header(commit_buffer_cursor + 1, "gpgsig-sha256", &commit_buffer_cursor))) + signature_alg = "sha256"; + } + + message = strstr(commit_buffer_cursor, "\n\n"); if (message) message += 2; @@ -694,16 +745,20 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, if (anonymize) { reencoded = anonymize_commit_message(); } else if (encoding) { - switch(reencode_mode) { + char *buf; + switch (reencode_mode) { case REENCODE_YES: - reencoded = reencode_string(message, "UTF-8", encoding); + buf = xstrfmt("%.*s", (int)encoding_len, encoding); + reencoded = reencode_string(message, "UTF-8", buf); + free(buf); break; case REENCODE_NO: break; case REENCODE_ABORT: - die("Encountered commit-specific encoding %s in commit " + die("Encountered commit-specific encoding %.*s in commit " "%s; use --reencode=[yes|no] to handle it", - encoding, oid_to_hex(&commit->object.oid)); + (int)encoding_len, encoding, + oid_to_hex(&commit->object.oid)); } } if (!commit->parents) @@ -714,8 +769,33 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, printf("%.*s\n%.*s\n", (int)(author_end - author), author, (int)(committer_end - committer), committer); + if (signature) { + switch (signed_commit_mode) { + case SIGN_ABORT: + die("encountered signed commit %s; use " + "--signed-commits=<mode> to handle it", + oid_to_hex(&commit->object.oid)); + case SIGN_WARN_VERBATIM: + warning("exporting signed commit %s", + oid_to_hex(&commit->object.oid)); + /* fallthru */ + case SIGN_VERBATIM: + printf("gpgsig %s\ndata %u\n%s", + signature_alg, + (unsigned)strlen(signature), + signature); + break; + case SIGN_WARN_STRIP: + warning("stripping signature from commit %s", + oid_to_hex(&commit->object.oid)); + /* fallthru */ + case SIGN_STRIP: + break; + } + free((char *)signature); + } if (!reencoded && encoding) - printf("encoding %s\n", encoding); + printf("encoding %.*s\n", (int)encoding_len, encoding); printf("data %u\n%s", (unsigned)(reencoded ? strlen(reencoded) : message @@ -828,22 +908,22 @@ static void handle_tag(const char *name, struct tag *tag) const char *signature = strstr(message, "\n-----BEGIN PGP SIGNATURE-----\n"); if (signature) - switch(signed_tag_mode) { - case SIGNED_TAG_ABORT: + switch (signed_tag_mode) { + case SIGN_ABORT: die("encountered signed tag %s; use " "--signed-tags=<mode> to handle it", oid_to_hex(&tag->object.oid)); - case WARN: + case SIGN_WARN_VERBATIM: warning("exporting signed tag %s", oid_to_hex(&tag->object.oid)); /* fallthru */ - case VERBATIM: + case SIGN_VERBATIM: break; - case WARN_STRIP: + case SIGN_WARN_STRIP: warning("stripping signature from tag %s", oid_to_hex(&tag->object.oid)); /* fallthru */ - case STRIP: + case SIGN_STRIP: message_size = signature + 1 - message; break; } @@ -853,7 +933,7 @@ static void handle_tag(const char *name, struct tag *tag) tagged = tag->tagged; tagged_mark = get_object_mark(tagged); if (!tagged_mark) { - switch(tag_of_filtered_mode) { + switch (tag_of_filtered_mode) { case TAG_FILTERING_ABORT: die("tag %s tags unexported object; use " "--tag-of-filtered-object=<mode> to handle it", @@ -965,7 +1045,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) continue; } - switch(commit->object.type) { + switch (commit->object.type) { case OBJ_COMMIT: break; case OBJ_BLOB: @@ -1189,6 +1269,7 @@ int cmd_fast_export(int argc, const char *prefix, struct repository *repo UNUSED) { + const char *env_signed_commits_noabort; struct rev_info revs; struct commit *commit; char *export_filename = NULL, @@ -1202,7 +1283,10 @@ int cmd_fast_export(int argc, N_("show progress after <n> objects")), OPT_CALLBACK(0, "signed-tags", &signed_tag_mode, N_("mode"), N_("select handling of signed tags"), - parse_opt_signed_tag_mode), + parse_opt_sign_mode), + OPT_CALLBACK(0, "signed-commits", &signed_commit_mode, N_("mode"), + N_("select handling of signed commits"), + parse_opt_sign_mode), OPT_CALLBACK(0, "tag-of-filtered-object", &tag_of_filtered_mode, N_("mode"), N_("select handling of tags that tag filtered objects"), parse_opt_tag_of_filtered_mode), @@ -1243,6 +1327,10 @@ int cmd_fast_export(int argc, if (argc == 1) usage_with_options (fast_export_usage, options); + env_signed_commits_noabort = getenv("FAST_EXPORT_SIGNED_COMMITS_NOABORT"); + if (env_signed_commits_noabort && *env_signed_commits_noabort) + signed_commit_mode = SIGN_WARN_STRIP; + /* we handle encodings */ git_config(git_default_config, NULL); diff --git a/builtin/fast-import.c b/builtin/fast-import.c index 0f86392761..e432e8d5a1 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -328,7 +328,7 @@ static void write_branch_report(FILE *rpt, struct branch *b) static void write_crash_report(const char *err) { - char *loc = git_pathdup("fast_import_crash_%"PRIuMAX, (uintmax_t) getpid()); + char *loc = repo_git_path(the_repository, "fast_import_crash_%"PRIuMAX, (uintmax_t) getpid()); FILE *rpt = fopen(loc, "w"); struct branch *b; unsigned long lu; @@ -798,8 +798,8 @@ static const char *create_index(void) if (c != last) die("internal consistency error creating the index"); - tmpfile = write_idx_file(NULL, idx, object_count, &pack_idx_opts, - pack_data->hash); + tmpfile = write_idx_file(the_hash_algo, NULL, idx, object_count, + &pack_idx_opts, pack_data->hash); free(idx); return tmpfile; } @@ -878,9 +878,10 @@ static void end_packfile(void) close_pack_windows(pack_data); finalize_hashfile(pack_file, cur_pack_oid.hash, FSYNC_COMPONENT_PACK, 0); - fixup_pack_header_footer(pack_data->pack_fd, pack_data->hash, - pack_data->pack_name, object_count, - cur_pack_oid.hash, pack_size); + fixup_pack_header_footer(the_hash_algo, pack_data->pack_fd, + pack_data->hash, pack_data->pack_name, + object_count, cur_pack_oid.hash, + pack_size); if (object_count <= unpack_limit) { if (!loosen_small_pack(pack_data)) { @@ -953,15 +954,15 @@ static int store_object( unsigned char hdr[96]; struct object_id oid; unsigned long hdrlen, deltalen; - git_hash_ctx c; + struct git_hash_ctx c; git_zstream s; hdrlen = format_object_header((char *)hdr, sizeof(hdr), type, dat->len); the_hash_algo->init_fn(&c); - the_hash_algo->update_fn(&c, hdr, hdrlen); - the_hash_algo->update_fn(&c, dat->buf, dat->len); - the_hash_algo->final_oid_fn(&oid, &c); + git_hash_update(&c, hdr, hdrlen); + git_hash_update(&c, dat->buf, dat->len); + git_hash_final_oid(&oid, &c); if (oidout) oidcpy(oidout, &oid); @@ -1095,7 +1096,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark) struct object_id oid; unsigned long hdrlen; off_t offset; - git_hash_ctx c; + struct git_hash_ctx c; git_zstream s; struct hashfile_checkpoint checkpoint; int status = Z_OK; @@ -1106,14 +1107,14 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark) || (pack_size + PACK_SIZE_THRESHOLD + len) < pack_size) cycle_packfile(); - the_hash_algo->unsafe_init_fn(&checkpoint.ctx); + hashfile_checkpoint_init(pack_file, &checkpoint); hashfile_checkpoint(pack_file, &checkpoint); offset = checkpoint.offset; hdrlen = format_object_header((char *)out_buf, out_sz, OBJ_BLOB, len); the_hash_algo->init_fn(&c); - the_hash_algo->update_fn(&c, out_buf, hdrlen); + git_hash_update(&c, out_buf, hdrlen); crc32_begin(pack_file); @@ -1131,7 +1132,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark) if (!n && feof(stdin)) die("EOF in data (%" PRIuMAX " bytes remaining)", len); - the_hash_algo->update_fn(&c, in_buf, n); + git_hash_update(&c, in_buf, n); s.next_in = in_buf; s.avail_in = n; len -= n; @@ -1157,7 +1158,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark) } } git_deflate_end(&s); - the_hash_algo->final_oid_fn(&oid, &c); + git_hash_final_oid(&oid, &c); if (oidout) oidcpy(oidout, &oid); @@ -2718,10 +2719,13 @@ static struct hash_list *parse_merge(unsigned int *count) static void parse_new_commit(const char *arg) { + static struct strbuf sig = STRBUF_INIT; static struct strbuf msg = STRBUF_INIT; + struct string_list siglines = STRING_LIST_INIT_NODUP; struct branch *b; char *author = NULL; char *committer = NULL; + char *sig_alg = NULL; char *encoding = NULL; struct hash_list *merge_list = NULL; unsigned int merge_count; @@ -2745,6 +2749,13 @@ static void parse_new_commit(const char *arg) } if (!committer) die("Expected committer but didn't get one"); + if (skip_prefix(command_buf.buf, "gpgsig ", &v)) { + sig_alg = xstrdup(v); + read_next_command(); + parse_data(&sig, 0, NULL); + read_next_command(); + } else + strbuf_setlen(&sig, 0); if (skip_prefix(command_buf.buf, "encoding ", &v)) { encoding = xstrdup(v); read_next_command(); @@ -2818,10 +2829,23 @@ static void parse_new_commit(const char *arg) strbuf_addf(&new_data, "encoding %s\n", encoding); + if (sig_alg) { + if (!strcmp(sig_alg, "sha1")) + strbuf_addstr(&new_data, "gpgsig "); + else if (!strcmp(sig_alg, "sha256")) + strbuf_addstr(&new_data, "gpgsig-sha256 "); + else + die("Expected gpgsig algorithm sha1 or sha256, got %s", sig_alg); + string_list_split_in_place(&siglines, sig.buf, "\n", -1); + strbuf_add_separated_string_list(&new_data, "\n ", &siglines); + strbuf_addch(&new_data, '\n'); + } strbuf_addch(&new_data, '\n'); strbuf_addbuf(&new_data, &msg); + string_list_clear(&siglines, 1); free(author); free(committer); + free(sig_alg); free(encoding); if (!store_object(OBJ_COMMIT, &new_data, NULL, &b->oid, next_mark)) @@ -3279,7 +3303,7 @@ static char* make_fast_import_path(const char *path) { if (!relative_marks_paths || is_absolute_path(path)) return prefix_filename(global_prefix, path); - return git_pathdup("info/fast-import/%s", path); + return repo_git_path(the_repository, "info/fast-import/%s", path); } static void option_import_marks(const char *marks, @@ -3565,8 +3589,7 @@ int cmd_fast_import(int argc, { unsigned int i; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage(fast_import_usage); + show_usage_if_asked(argc, argv, fast_import_usage); reset_pack_idx_option(&pack_idx_opts); git_pack_config(); diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index bed2816c2d..d07eec9e55 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -75,6 +75,8 @@ int cmd_fetch_pack(int argc, list_objects_filter_init(&args.filter_options); args.uploadpack = "git-upload-pack"; + show_usage_if_asked(argc, argv, fetch_pack_usage); + for (i = 1; i < argc && *argv[i] == '-'; i++) { const char *arg = argv[i]; diff --git a/builtin/fetch.c b/builtin/fetch.c index fe2b26c74a..02af505469 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1617,13 +1617,13 @@ static void report_set_head(const char *remote, const char *head_name, strbuf_release(&buf_prefix); } -static int set_head(const struct ref *remote_refs, int follow_remote_head, - const char *no_warn_branch) +static int set_head(const struct ref *remote_refs, struct remote *remote) { - int result = 0, create_only, is_bare, was_detached; + int result = 0, create_only, baremirror, was_detached; struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT, b_local_head = STRBUF_INIT; - const char *remote = gtransport->remote->name; + int follow_remote_head = remote->follow_remote_head; + const char *no_warn_branch = remote->no_warn_branch; char *head_name = NULL; struct ref *ref, *matches; struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map; @@ -1655,17 +1655,17 @@ static int set_head(const struct ref *remote_refs, int follow_remote_head, if (!head_name) goto cleanup; - is_bare = is_bare_repository(); - create_only = follow_remote_head == FOLLOW_REMOTE_ALWAYS ? 0 : !is_bare; - if (is_bare) { + baremirror = is_bare_repository() && remote->mirror; + create_only = follow_remote_head == FOLLOW_REMOTE_ALWAYS ? 0 : !baremirror; + if (baremirror) { strbuf_addstr(&b_head, "HEAD"); strbuf_addf(&b_remote_head, "refs/heads/%s", head_name); } else { - strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote); - strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote, head_name); + strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote->name); + strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote->name, head_name); } /* make sure it's valid */ - if (!is_bare && !refs_ref_exists(refs, b_remote_head.buf)) { + if (!baremirror && !refs_ref_exists(refs, b_remote_head.buf)) { result = 1; goto cleanup; } @@ -1678,7 +1678,7 @@ static int set_head(const struct ref *remote_refs, int follow_remote_head, if (verbosity >= 0 && follow_remote_head == FOLLOW_REMOTE_WARN && (!no_warn_branch || strcmp(no_warn_branch, head_name))) - report_set_head(remote, head_name, &b_local_head, was_detached); + report_set_head(remote->name, head_name, &b_local_head, was_detached); cleanup: free(head_name); @@ -1718,7 +1718,6 @@ static int do_fetch(struct transport *transport, const struct ref *remote_refs; struct transport_ls_refs_options transport_ls_refs_options = TRANSPORT_LS_REFS_OPTIONS_INIT; - int must_list_refs = 1; struct fetch_head fetch_head = { 0 }; struct strbuf err = STRBUF_INIT; @@ -1737,21 +1736,7 @@ static int do_fetch(struct transport *transport, } if (rs->nr) { - int i; - refspec_ref_prefixes(rs, &transport_ls_refs_options.ref_prefixes); - - /* - * We can avoid listing refs if all of them are exact - * OIDs - */ - must_list_refs = 0; - for (i = 0; i < rs->nr; i++) { - if (!rs->items[i].exact_sha1) { - must_list_refs = 1; - break; - } - } } else { struct branch *branch = branch_get(NULL); @@ -1766,21 +1751,30 @@ static int do_fetch(struct transport *transport, branch->merge[i]->src); } } - } - if (tags == TAGS_SET || tags == TAGS_DEFAULT) { - must_list_refs = 1; - if (transport_ls_refs_options.ref_prefixes.nr) + /* + * If there are no refs specified to fetch, then we just + * fetch HEAD; mention that to narrow the advertisement. + */ + if (!transport_ls_refs_options.ref_prefixes.nr) strvec_push(&transport_ls_refs_options.ref_prefixes, - "refs/tags/"); + "HEAD"); } - if (uses_remote_tracking(transport, rs)) { - must_list_refs = 1; - strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD"); - } + if (tags == TAGS_SET || tags == TAGS_DEFAULT) + strvec_push(&transport_ls_refs_options.ref_prefixes, + "refs/tags/"); - if (must_list_refs) { + if (transport_ls_refs_options.ref_prefixes.nr && + uses_remote_tracking(transport, rs)) + strvec_push(&transport_ls_refs_options.ref_prefixes, + "HEAD"); + + /* + * Only initiate ref listing if we have at least one ref we want to + * know about. + */ + if (transport_ls_refs_options.ref_prefixes.nr) { trace2_region_enter("fetch", "remote_refs", the_repository); remote_refs = transport_get_remote_refs(transport, &transport_ls_refs_options); @@ -1924,8 +1918,7 @@ static int do_fetch(struct transport *transport, "you need to specify exactly one branch with the --set-upstream option")); } } - if (set_head(remote_refs, transport->remote->follow_remote_head, - transport->remote->no_warn_branch)) + if (set_head(remote_refs, transport->remote)) ; /* * Way too many cases where this can go wrong diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 715745a262..3d2207ec77 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "commit.h" #include "config.h" @@ -20,7 +19,7 @@ static char const * const for_each_ref_usage[] = { int cmd_for_each_ref(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct ref_sorting *sorting; struct string_list sorting_options = STRING_LIST_INIT_DUP; @@ -63,7 +62,7 @@ int cmd_for_each_ref(int argc, format.format = "%(objectname) %(objecttype)\t%(refname)"; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); /* Set default (refname) sorting */ string_list_append(&sorting_options, "refname"); @@ -108,7 +107,6 @@ int cmd_for_each_ref(int argc, filter_and_format_refs(&filter, flags, sorting, &format); ref_filter_clear(&filter); - ref_format_clear(&format); ref_sorting_release(sorting); strvec_clear(&vec); return 0; diff --git a/builtin/fsck.c b/builtin/fsck.c index 0196c54eb6..8fbd1d6334 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -50,6 +50,7 @@ static int verbose; static int show_progress = -1; static int show_dangling = 1; static int name_objects; +static int check_references = 1; #define ERROR_OBJECT 01 #define ERROR_REACHABLE 02 #define ERROR_PACK 04 @@ -197,7 +198,8 @@ static int traverse_reachable(void) unsigned int nr = 0; int result = 0; if (show_progress) - progress = start_delayed_progress(_("Checking connectivity"), 0); + progress = start_delayed_progress(the_repository, + _("Checking connectivity"), 0); while (pending.nr) { result |= traverse_one_object(object_array_pop(&pending)); display_progress(progress, ++nr); @@ -325,7 +327,7 @@ static void check_unreachable_object(struct object *obj) printable_type(&obj->oid, obj->type), describe_object(&obj->oid)); if (write_lost_and_found) { - char *filename = git_pathdup("lost-found/%s/%s", + char *filename = repo_git_path(the_repository, "lost-found/%s/%s", obj->type == OBJ_COMMIT ? "commit" : "other", describe_object(&obj->oid)); FILE *f; @@ -703,7 +705,8 @@ static void fsck_object_dir(const char *path) fprintf_ln(stderr, _("Checking object directory")); if (show_progress) - progress = start_progress(_("Checking object directories"), 256); + progress = start_progress(the_repository, + _("Checking object directories"), 256); for_each_loose_file_in_objdir(path, fsck_loose, fsck_cruft, fsck_subdir, &cb_data); @@ -879,7 +882,8 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress) if (show_progress) { for (struct packed_git *p = get_all_packs(r); p; p = p->next) pack_count++; - progress = start_delayed_progress("Verifying reverse pack-indexes", pack_count); + progress = start_delayed_progress(the_repository, + "Verifying reverse pack-indexes", pack_count); pack_count = 0; } @@ -902,11 +906,37 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress) return res; } +static void fsck_refs(struct repository *r) +{ + struct child_process refs_verify = CHILD_PROCESS_INIT; + struct progress *progress = NULL; + + if (show_progress) + progress = start_progress(r, _("Checking ref database"), 1); + + if (verbose) + fprintf_ln(stderr, _("Checking ref database")); + + child_process_init(&refs_verify); + refs_verify.git_cmd = 1; + strvec_pushl(&refs_verify.args, "refs", "verify", NULL); + if (verbose) + strvec_push(&refs_verify.args, "--verbose"); + if (check_strict) + strvec_push(&refs_verify.args, "--strict"); + + if (run_command(&refs_verify)) + errors_found |= ERROR_REFS; + + display_progress(progress, 1); + stop_progress(&progress); +} + static char const * const fsck_usage[] = { N_("git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" " [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" - " [--[no-]name-objects] [<object>...]"), + " [--[no-]name-objects] [--[no-]references] [<object>...]"), NULL }; @@ -925,6 +955,7 @@ static struct option fsck_opts[] = { N_("write dangling objects in .git/lost-found")), OPT_BOOL(0, "progress", &show_progress, N_("show progress")), OPT_BOOL(0, "name-objects", &name_objects, N_("show verbose names for reachable objects")), + OPT_BOOL(0, "references", &check_references, N_("check reference database consistency")), OPT_END(), }; @@ -967,6 +998,9 @@ int cmd_fsck(int argc, git_config(git_fsck_config, &fsck_obj_options); prepare_repo_settings(the_repository); + if (check_references) + fsck_refs(the_repository); + if (connectivity_only) { for_each_loose_object(mark_loose_for_connectivity, NULL, 0); for_each_packed_object(the_repository, @@ -989,7 +1023,8 @@ int cmd_fsck(int argc, total += p->num_objects; } - progress = start_progress(_("Checking objects"), total); + progress = start_progress(the_repository, + _("Checking objects"), total); } for (p = get_all_packs(the_repository); p; p = p->next) { @@ -1053,7 +1088,7 @@ int cmd_fsck(int argc, struct worktree *wt = *p; struct index_state istate = INDEX_STATE_INIT(the_repository); - char *path; + char *path, *wt_gitdir; /* * Make a copy since the buffer is reusable @@ -1061,9 +1096,13 @@ int cmd_fsck(int argc, * while we're examining the index. */ path = xstrdup(worktree_git_path(the_repository, wt, "index")); - read_index_from(&istate, path, get_worktree_git_dir(wt)); + wt_gitdir = get_worktree_git_dir(wt); + + read_index_from(&istate, path, wt_gitdir); fsck_index(&istate, path, wt->is_current); + discard_index(&istate); + free(wt_gitdir); free(path); } free_worktrees(worktrees); diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index 029dc64d6c..0820e524f1 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -1598,8 +1598,8 @@ int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix UNUSED OPT_END() }; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_fsmonitor__daemon_usage, options); + show_usage_with_options_if_asked(argc, argv, + builtin_fsmonitor__daemon_usage, options); die(_("fsmonitor--daemon not supported on this platform")); } diff --git a/builtin/gc.c b/builtin/gc.c index a9b1c36de2..99431fd467 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -99,9 +99,11 @@ static void process_log_file(void) /* There was some error recorded in the lock file */ commit_lock_file(&log_lock); } else { + char *path = repo_git_path(the_repository, "gc.log"); /* No error, clean up any old gc.log */ - unlink(git_path("gc.log")); + unlink(path); rollback_lock_file(&log_lock); + free(path); } } @@ -139,6 +141,7 @@ struct gc_config { char *prune_worktrees_expire; char *repack_filter; char *repack_filter_to; + char *repack_expire_to; unsigned long big_pack_threshold; unsigned long max_delta_cache_size; /* @@ -299,8 +302,11 @@ static int too_many_loose_objects(struct gc_config *cfg) int num_loose = 0; int needed = 0; const unsigned hexsz_loose = the_hash_algo->hexsz - 2; + char *path; - dir = opendir(git_path("objects/17")); + path = repo_git_path(the_repository, "objects/17"); + dir = opendir(path); + free(path); if (!dir) return 0; @@ -445,7 +451,8 @@ static int keep_one_pack(struct string_list_item *item, void *data UNUSED) static void add_repack_all_option(struct gc_config *cfg, struct string_list *keep_pack) { - if (cfg->prune_expire && !strcmp(cfg->prune_expire, "now")) + if (cfg->prune_expire && !strcmp(cfg->prune_expire, "now") + && !(cfg->cruft_packs && cfg->repack_expire_to)) strvec_push(&repack, "-a"); else if (cfg->cruft_packs) { strvec_push(&repack, "--cruft"); @@ -454,6 +461,8 @@ static void add_repack_all_option(struct gc_config *cfg, if (cfg->max_cruft_size) strvec_pushf(&repack, "--max-cruft-size=%lu", cfg->max_cruft_size); + if (cfg->repack_expire_to) + strvec_pushf(&repack, "--expire-to=%s", cfg->repack_expire_to); } else { strvec_push(&repack, "-A"); if (cfg->prune_expire) @@ -546,7 +555,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) if (xgethostname(my_host, sizeof(my_host))) xsnprintf(my_host, sizeof(my_host), "unknown"); - pidfile_path = git_pathdup("gc.pid"); + pidfile_path = repo_git_path(the_repository, "gc.pid"); fd = hold_lock_file_for_update(&lock, pidfile_path, LOCK_DIE_ON_ERROR); if (!force) { @@ -607,7 +616,7 @@ static int report_last_gc_error(void) int ret = 0; ssize_t len; struct stat st; - char *gc_log_path = git_pathdup("gc.log"); + char *gc_log_path = repo_git_path(the_repository, "gc.log"); if (stat(gc_log_path, &st)) { if (errno == ENOENT) @@ -688,7 +697,6 @@ struct repository *repo UNUSED) const char *prune_expire_sentinel = "sentinel"; const char *prune_expire_arg = prune_expire_sentinel; int ret; - struct option builtin_gc_options[] = { OPT__QUIET(&quiet, N_("suppress progress reporting")), { OPTION_STRING, 0, "prune", &prune_expire_arg, N_("date"), @@ -707,11 +715,13 @@ struct repository *repo UNUSED) PARSE_OPT_NOCOMPLETE), OPT_BOOL(0, "keep-largest-pack", &keep_largest_pack, N_("repack all other packs except the largest pack")), + OPT_STRING(0, "expire-to", &cfg.repack_expire_to, N_("dir"), + N_("pack prefix to store a pack containing pruned objects")), OPT_END() }; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_gc_usage, builtin_gc_options); + show_usage_with_options_if_asked(argc, argv, + builtin_gc_usage, builtin_gc_options); strvec_pushl(&reflog, "reflog", "expire", "--all", NULL); strvec_pushl(&repack, "repack", "-d", "-l", NULL); @@ -821,11 +831,12 @@ struct repository *repo UNUSED) } if (daemonized) { - hold_lock_file_for_update(&log_lock, - git_path("gc.log"), + char *path = repo_git_path(the_repository, "gc.log"); + hold_lock_file_for_update(&log_lock, path, LOCK_DIE_ON_ERROR); dup2(get_lock_file_fd(&log_lock), 2); atexit(process_log_file_at_exit); + free(path); } gc_before_repack(&opts, &cfg); @@ -887,8 +898,11 @@ struct repository *repo UNUSED) warning(_("There are too many unreachable loose objects; " "run 'git prune' to remove them.")); - if (!daemonized) - unlink(git_path("gc.log")); + if (!daemonized) { + char *path = repo_git_path(the_repository, "gc.log"); + unlink(path); + free(path); + } out: gc_config_release(&cfg); @@ -1909,7 +1923,7 @@ static int get_random_minute(void) if (getenv("GIT_TEST_MAINT_SCHEDULER")) return 13; - return git_rand() % 60; + return git_rand(0) % 60; } static int is_launchctl_available(void) diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c index 6bec0d1854..e4cd1627b4 100644 --- a/builtin/get-tar-commit-id.c +++ b/builtin/get-tar-commit-id.c @@ -13,7 +13,7 @@ static const char builtin_get_tar_commit_id_usage[] = #define HEADERSIZE (2 * RECORDSIZE) int cmd_get_tar_commit_id(int argc, - const char **argv UNUSED, + const char **argv, const char *prefix, struct repository *repo UNUSED) { @@ -27,6 +27,8 @@ int cmd_get_tar_commit_id(int argc, BUG_ON_NON_EMPTY_PREFIX(prefix); + show_usage_if_asked(argc, argv, builtin_get_tar_commit_id_usage); + if (argc != 1) usage(builtin_get_tar_commit_id_usage); diff --git a/builtin/grep.c b/builtin/grep.c index d00ee76f24..d1427290f7 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -1084,7 +1084,7 @@ int cmd_grep(int argc, } if (show_in_pager == default_pager) - show_in_pager = git_pager(1); + show_in_pager = git_pager(the_repository, 1); if (show_in_pager) { opt.color = 0; opt.name_only = 1; @@ -1246,7 +1246,7 @@ int cmd_grep(int argc, } if (!show_in_pager && !opt.status_only) - setup_pager(); + setup_pager(the_repository); die_for_incompatible_opt3(!use_index, "--no-index", untracked, "--untracked", diff --git a/builtin/help.c b/builtin/help.c index 05136279cf..c257079ceb 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -658,7 +658,7 @@ int cmd_help(int argc, case HELP_ACTION_ALL: opt_mode_usage(argc, "--all", help_format); if (verbose) { - setup_pager(); + setup_pager(the_repository); list_all_cmds_help(show_external_commands, show_aliases); return 0; @@ -692,7 +692,7 @@ int cmd_help(int argc, return 0; case HELP_ACTION_CONFIG: opt_mode_usage(argc, "--config", help_format); - setup_pager(); + setup_pager(the_repository); list_config_help(SHOW_CONFIG_HUMAN); printf("\n%s\n", _("'git help config' for more information")); return 0; diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 0b62b2589f..52cc97d52c 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -151,7 +151,7 @@ static unsigned int input_offset, input_len; static off_t consumed_bytes; static off_t max_input_size; static unsigned deepest_delta; -static git_hash_ctx input_ctx; +static struct git_hash_ctx input_ctx; static uint32_t input_crc32; static int input_fd, output_fd; static const char *curr_pack; @@ -282,7 +282,8 @@ static unsigned check_objects(void) max = get_max_object_index(); if (verbose) - progress = start_delayed_progress(_("Checking objects"), max); + progress = start_delayed_progress(the_repository, + _("Checking objects"), max); for (i = 0; i < max; i++) { foreign_nr += check_object(get_indexed_object(i)); @@ -300,7 +301,7 @@ static void flush(void) if (input_offset) { if (output_fd >= 0) write_or_die(output_fd, input_buffer, input_offset); - the_hash_algo->update_fn(&input_ctx, input_buffer, input_offset); + git_hash_update(&input_ctx, input_buffer, input_offset); memmove(input_buffer, input_buffer + input_offset, input_len); input_offset = 0; } @@ -379,16 +380,18 @@ static const char *open_pack_file(const char *pack_name) static void parse_pack_header(void) { - struct pack_header *hdr = fill(sizeof(struct pack_header)); + unsigned char *hdr = fill(sizeof(struct pack_header)); /* Header consistency check */ - if (hdr->hdr_signature != htonl(PACK_SIGNATURE)) + if (get_be32(hdr) != PACK_SIGNATURE) die(_("pack signature mismatch")); - if (!pack_version_ok(hdr->hdr_version)) + hdr += 4; + if (!pack_version_ok_native(get_be32(hdr))) die(_("pack version %"PRIu32" unsupported"), - ntohl(hdr->hdr_version)); + get_be32(hdr)); + hdr += 4; - nr_objects = ntohl(hdr->hdr_entries); + nr_objects = get_be32(hdr); use(sizeof(struct pack_header)); } @@ -472,14 +475,14 @@ static void *unpack_entry_data(off_t offset, unsigned long size, int status; git_zstream stream; void *buf; - git_hash_ctx c; + struct git_hash_ctx c; char hdr[32]; int hdrlen; if (!is_delta_type(type)) { hdrlen = format_object_header(hdr, sizeof(hdr), type, size); the_hash_algo->init_fn(&c); - the_hash_algo->update_fn(&c, hdr, hdrlen); + git_hash_update(&c, hdr, hdrlen); } else oid = NULL; if (type == OBJ_BLOB && size > big_file_threshold) @@ -499,7 +502,7 @@ static void *unpack_entry_data(off_t offset, unsigned long size, status = git_inflate(&stream, 0); use(input_len - stream.avail_in); if (oid) - the_hash_algo->update_fn(&c, last_out, stream.next_out - last_out); + git_hash_update(&c, last_out, stream.next_out - last_out); if (buf == fixed_buf) { stream.next_out = buf; stream.avail_out = sizeof(fixed_buf); @@ -509,7 +512,7 @@ static void *unpack_entry_data(off_t offset, unsigned long size, bad_object(offset, _("inflate returned %d"), status); git_inflate_end(&stream); if (oid) - the_hash_algo->final_oid_fn(oid, &c); + git_hash_final_oid(oid, &c); return buf == fixed_buf ? NULL : buf; } @@ -1245,10 +1248,11 @@ static void parse_pack_objects(unsigned char *hash) struct ofs_delta_entry *ofs_delta = ofs_deltas; struct object_id ref_delta_oid; struct stat st; - git_hash_ctx tmp_ctx; + struct git_hash_ctx tmp_ctx; if (verbose) progress = start_progress( + the_repository, progress_title ? progress_title : from_stdin ? _("Receiving objects") : _("Indexing objects"), nr_objects); @@ -1282,9 +1286,8 @@ static void parse_pack_objects(unsigned char *hash) /* Check pack integrity */ flush(); - the_hash_algo->init_fn(&tmp_ctx); - the_hash_algo->clone_fn(&tmp_ctx, &input_ctx); - the_hash_algo->final_fn(hash, &tmp_ctx); + git_hash_clone(&tmp_ctx, &input_ctx); + git_hash_final(hash, &tmp_ctx); if (!hasheq(fill(the_hash_algo->rawsz), hash, the_repository->hash_algo)) die(_("pack is corrupted (SHA1 mismatch)")); use(the_hash_algo->rawsz); @@ -1329,7 +1332,8 @@ static void resolve_deltas(struct pack_idx_option *opts) QSORT(ref_deltas, nr_ref_deltas, compare_ref_delta_entry); if (verbose || show_resolving_progress) - progress = start_progress(_("Resolving deltas"), + progress = start_progress(the_repository, + _("Resolving deltas"), nr_ref_deltas + nr_ofs_deltas); nr_dispatched = 0; @@ -1387,7 +1391,7 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha strbuf_release(&msg); finalize_hashfile(f, tail_hash, FSYNC_COMPONENT_PACK, 0); hashcpy(read_hash, pack_hash, the_repository->hash_algo); - fixup_pack_header_footer(output_fd, pack_hash, + fixup_pack_header_footer(the_hash_algo, output_fd, pack_hash, curr_pack, nr_objects, read_hash, consumed_bytes-the_hash_algo->rawsz); if (!hasheq(read_hash, tail_hash, the_repository->hash_algo)) @@ -1897,8 +1901,7 @@ int cmd_index_pack(int argc, */ fetch_if_missing = 0; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage(index_pack_usage); + show_usage_if_asked(argc, argv, index_pack_usage); disable_replace_refs(); fsck_options.walk = mark_link; @@ -1954,19 +1957,11 @@ int cmd_index_pack(int argc, warning(_("no threads support, ignoring %s"), arg); nr_threads = 1; } - } else if (starts_with(arg, "--pack_header=")) { - struct pack_header *hdr; - char *c; - - hdr = (struct pack_header *)input_buffer; - hdr->hdr_signature = htonl(PACK_SIGNATURE); - hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10)); - if (*c != ',') - die(_("bad %s"), arg); - hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10)); - if (*c) - die(_("bad %s"), arg); - input_len = sizeof(*hdr); + } else if (skip_prefix(arg, "--pack_header=", &arg)) { + if (parse_pack_header_option(arg, + input_buffer, + &input_len) < 0) + die(_("bad --pack_header: %s"), arg); } else if (!strcmp(arg, "-v")) { verbose = 1; } else if (!strcmp(arg, "--progress-title")) { @@ -2093,11 +2088,12 @@ int cmd_index_pack(int argc, ALLOC_ARRAY(idx_objects, nr_objects); for (i = 0; i < nr_objects; i++) idx_objects[i] = &objects[i].idx; - curr_index = write_idx_file(index_name, idx_objects, nr_objects, &opts, pack_hash); + curr_index = write_idx_file(the_hash_algo, index_name, idx_objects, + nr_objects, &opts, pack_hash); if (rev_index) - curr_rev_index = write_rev_file(rev_index_name, idx_objects, - nr_objects, pack_hash, - opts.flags); + curr_rev_index = write_rev_file(the_hash_algo, rev_index_name, + idx_objects, nr_objects, + pack_hash, opts.flags); free(idx_objects); if (!verify) diff --git a/builtin/init-db.c b/builtin/init-db.c index 096f96b9c4..196dccdd77 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -132,8 +132,8 @@ int cmd_init_db(int argc, * and we know shared_repository should always be 0; * but just in case we play safe. */ - saved = get_shared_repository(); - set_shared_repository(0); + saved = repo_settings_get_shared_repository(the_repository); + repo_settings_set_shared_repository(the_repository, 0); switch (safe_create_leading_directories_const(argv[0])) { case SCLD_OK: case SCLD_PERMS: @@ -145,7 +145,7 @@ int cmd_init_db(int argc, die_errno(_("cannot mkdir %s"), argv[0]); break; } - set_shared_repository(saved); + repo_settings_set_shared_repository(the_repository, saved); if (mkdir(argv[0], 0777) < 0) die_errno(_("cannot mkdir %s"), argv[0]); mkdir_tried = 1; @@ -175,7 +175,7 @@ int cmd_init_db(int argc, } if (init_shared_repository != -1) - set_shared_repository(init_shared_repository); + repo_settings_set_shared_repository(the_repository, init_shared_repository); /* * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR diff --git a/builtin/log.c b/builtin/log.c index 75e1b34123..04a6ef97bc 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -6,7 +6,6 @@ */ #define USE_THE_REPOSITORY_VARIABLE -#define DISABLE_SIGN_COMPARE_WARNINGS #include "builtin.h" #include "abspath.h" @@ -209,7 +208,6 @@ static void cmd_log_init_defaults(struct rev_info *rev, static void set_default_decoration_filter(struct decoration_filter *decoration_filter) { - int i; char *value = NULL; struct string_list *include = decoration_filter->include_ref_pattern; const struct string_list *config_exclude; @@ -243,7 +241,7 @@ static void set_default_decoration_filter(struct decoration_filter *decoration_f * No command-line or config options were given, so * populate with sensible defaults. */ - for (i = 0; i < ARRAY_SIZE(ref_namespace); i++) { + for (size_t i = 0; i < ARRAY_SIZE(ref_namespace); i++) { if (!ref_namespace[i].decoration) continue; @@ -369,7 +367,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix, if (rev->line_level_traverse) line_log_init(rev, line_cb.prefix, &line_cb.args); - setup_pager(); + setup_pager(the_repository); } static void cmd_log_init(int argc, const char **argv, const char *prefix, @@ -717,14 +715,14 @@ static int show_tag_object(const struct object_id *oid, struct rev_info *rev) unsigned long size; enum object_type type; char *buf = repo_read_object_file(the_repository, oid, &type, &size); - int offset = 0; + unsigned long offset = 0; if (!buf) return error(_("could not read object %s"), oid_to_hex(oid)); assert(type == OBJ_TAG); while (offset < size && buf[offset] != '\n') { - int new_offset = offset + 1; + unsigned long new_offset = offset + 1; const char *ident; while (new_offset < size && buf[new_offset++] != '\n') ; /* do nothing */ @@ -1316,24 +1314,25 @@ static void print_signature(const char *signature, FILE *file) static char *find_branch_name(struct rev_info *rev) { - int i, positive = -1; struct object_id branch_oid; const struct object_id *tip_oid; const char *ref, *v; char *full_ref, *branch = NULL; + int interesting_found = 0; + size_t idx; - for (i = 0; i < rev->cmdline.nr; i++) { + for (size_t i = 0; i < rev->cmdline.nr; i++) { if (rev->cmdline.rev[i].flags & UNINTERESTING) continue; - if (positive < 0) - positive = i; - else + if (interesting_found) return NULL; + interesting_found = 1; + idx = i; } - if (positive < 0) + if (!interesting_found) return NULL; - ref = rev->cmdline.rev[positive].name; - tip_oid = &rev->cmdline.rev[positive].item->oid; + ref = rev->cmdline.rev[idx].name; + tip_oid = &rev->cmdline.rev[idx].item->oid; if (repo_dwim_ref(the_repository, ref, strlen(ref), &branch_oid, &full_ref, 0) && skip_prefix(full_ref, "refs/heads/", &v) && @@ -1746,11 +1745,12 @@ struct base_tree_info { static struct commit *get_base_commit(const struct format_config *cfg, struct commit **list, - int total) + size_t total) { struct commit *base = NULL; struct commit **rev; - int i = 0, rev_nr = 0, auto_select, die_on_failure, ret; + int auto_select, die_on_failure, ret; + size_t i = 0, rev_nr = 0; switch (cfg->auto_base) { case AUTO_BASE_NEVER: @@ -1885,13 +1885,12 @@ define_commit_slab(commit_base, int); static void prepare_bases(struct base_tree_info *bases, struct commit *base, struct commit **list, - int total) + size_t total) { struct commit *commit; struct rev_info revs; struct diff_options diffopt; struct commit_base commit_base; - int i; if (!base) return; @@ -1906,7 +1905,7 @@ static void prepare_bases(struct base_tree_info *bases, repo_init_revisions(the_repository, &revs, NULL); revs.max_parents = 1; revs.topo_order = 1; - for (i = 0; i < total; i++) { + for (size_t i = 0; i < total; i++) { list[i]->object.flags &= ~UNINTERESTING; add_pending_object(&revs, &list[i]->object, "rev_list"); *commit_base_at(&commit_base, list[i]) = 1; @@ -2007,7 +2006,7 @@ int cmd_format_patch(int argc, struct rev_info rev; char *to_free = NULL; struct setup_revision_opt s_r_opt; - int nr = 0, total, i; + size_t nr = 0, total, i; int use_stdout = 0; int start_number = -1; int just_numbers = 0; @@ -2183,7 +2182,7 @@ int cmd_format_patch(int argc, fmt_patch_suffix = cfg.fmt_patch_suffix; /* Make sure "0000-$sub.patch" gives non-negative length for $sub */ - if (cfg.log.fmt_patch_name_max <= strlen("0000-") + strlen(fmt_patch_suffix)) + if (cfg.log.fmt_patch_name_max <= cast_size_t_to_int(strlen("0000-") + strlen(fmt_patch_suffix))) cfg.log.fmt_patch_name_max = strlen("0000-") + strlen(fmt_patch_suffix); if (cover_from_description_arg) @@ -2296,7 +2295,7 @@ int cmd_format_patch(int argc, rev.commit_format = CMIT_FMT_MBOXRD; if (use_stdout) { - setup_pager(); + setup_pager(the_repository); } else if (!rev.diffopt.close_file) { int saved; @@ -2310,8 +2309,8 @@ int cmd_format_patch(int argc, * We consider <outdir> as 'outside of gitdir', therefore avoid * applying adjust_shared_perm in s-c-l-d. */ - saved = get_shared_repository(); - set_shared_repository(0); + saved = repo_settings_get_shared_repository(the_repository); + repo_settings_set_shared_repository(the_repository, 0); switch (safe_create_leading_directories_const(output_directory)) { case SCLD_OK: case SCLD_EXISTS: @@ -2320,7 +2319,7 @@ int cmd_format_patch(int argc, die(_("could not create leading directories " "of '%s'"), output_directory); } - set_shared_repository(saved); + repo_settings_set_shared_repository(the_repository, saved); if (mkdir(output_directory, 0777) < 0 && errno != EEXIST) die_errno(_("could not create directory '%s'"), output_directory); @@ -2499,12 +2498,16 @@ int cmd_format_patch(int argc, rev.add_signoff = cfg.do_signoff; if (show_progress) - progress = start_delayed_progress(_("Generating patches"), total); - while (0 <= --nr) { + progress = start_delayed_progress(the_repository, + _("Generating patches"), total); + for (i = 0; i < nr; i++) { + size_t idx = nr - i - 1; int shown; - display_progress(progress, total - nr); - commit = list[nr]; - rev.nr = total - nr + (start_number - 1); + + display_progress(progress, total - idx); + commit = list[idx]; + rev.nr = total - idx + (start_number - 1); + /* Make the second and subsequent mails replies to the first */ if (cfg.thread) { /* Have we already had a message ID? */ diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 15499cd12b..70a377e9c0 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -6,7 +6,6 @@ * Copyright (C) Linus Torvalds, 2005 */ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "builtin.h" @@ -245,12 +244,13 @@ static void show_submodule(struct repository *superproject, repo_clear(&subrepo); } -static void expand_objectsize(struct strbuf *line, const struct object_id *oid, +static void expand_objectsize(struct repository *repo, struct strbuf *line, + const struct object_id *oid, const enum object_type type, unsigned int padded) { if (type == OBJ_BLOB) { unsigned long size; - if (oid_object_info(the_repository, oid, &size) < 0) + if (oid_object_info(repo, oid, &size) < 0) die(_("could not get object info about '%s'"), oid_to_hex(oid)); if (padded) @@ -283,10 +283,10 @@ static void show_ce_fmt(struct repository *repo, const struct cache_entry *ce, else if (skip_prefix(format, "(objecttype)", &format)) strbuf_addstr(&sb, type_name(object_type(ce->ce_mode))); else if (skip_prefix(format, "(objectsize:padded)", &format)) - expand_objectsize(&sb, &ce->oid, + expand_objectsize(repo, &sb, &ce->oid, object_type(ce->ce_mode), 1); else if (skip_prefix(format, "(objectsize)", &format)) - expand_objectsize(&sb, &ce->oid, + expand_objectsize(repo, &sb, &ce->oid, object_type(ce->ce_mode), 0); else if (skip_prefix(format, "(stage)", &format)) strbuf_addf(&sb, "%d", ce_stage(ce)); @@ -348,7 +348,7 @@ static void show_ce(struct repository *repo, struct dir_struct *dir, } } -static void show_ru_info(struct index_state *istate) +static void show_ru_info(struct repository *repo, struct index_state *istate) { struct string_list_item *item; @@ -370,7 +370,7 @@ static void show_ru_info(struct index_state *istate) if (!ui->mode[i]) continue; printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i], - repo_find_unique_abbrev(the_repository, &ui->oid[i], abbrev), + repo_find_unique_abbrev(repo, &ui->oid[i], abbrev), i + 1); write_name(path); } @@ -567,7 +567,7 @@ static int option_parse_exclude_standard(const struct option *opt, int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix, - struct repository *repo UNUSED) + struct repository *repo) { int require_work_tree = 0, show_tag = 0, i; char *max_prefix; @@ -644,18 +644,18 @@ int cmd_ls_files(int argc, }; int ret = 0; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(ls_files_usage, builtin_ls_files_options); + show_usage_with_options_if_asked(argc, argv, + ls_files_usage, builtin_ls_files_options); - prepare_repo_settings(the_repository); - the_repository->settings.command_requires_full_index = 0; + prepare_repo_settings(repo); + repo->settings.command_requires_full_index = 0; prefix = cmd_prefix; if (prefix) prefix_len = strlen(prefix); - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); - if (repo_read_index(the_repository) < 0) + if (repo_read_index(repo) < 0) die("index file corrupt"); argc = parse_options(argc, argv, prefix, builtin_ls_files_options, @@ -724,7 +724,7 @@ int cmd_ls_files(int argc, max_prefix = common_prefix(&pathspec); max_prefix_len = get_common_prefix_len(max_prefix); - prune_index(the_repository->index, max_prefix, max_prefix_len); + prune_index(repo->index, max_prefix, max_prefix_len); /* Treat unmatching pathspec elements as errors */ if (pathspec.nr && error_unmatch) @@ -748,13 +748,13 @@ int cmd_ls_files(int argc, */ if (show_stage || show_unmerged) die(_("options '%s' and '%s' cannot be used together"), "ls-files --with-tree", "-s/-u"); - overlay_tree_on_index(the_repository->index, with_tree, max_prefix); + overlay_tree_on_index(repo->index, with_tree, max_prefix); } - show_files(the_repository, &dir); + show_files(repo, &dir); if (show_resolve_undo) - show_ru_info(the_repository->index); + show_ru_info(repo, repo->index); if (ps_matched && report_path_error(ps_matched, &pathspec)) { fprintf(stderr, "Did you forget to 'git add'?\n"); diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c index e17dec27b1..8de7ba7de1 100644 --- a/builtin/mailinfo.c +++ b/builtin/mailinfo.c @@ -83,7 +83,7 @@ int cmd_mailinfo(int argc, OPT_END() }; - setup_mailinfo(&mi); + setup_mailinfo(the_repository, &mi); meta_charset.policy = CHARSET_DEFAULT; argc = parse_options(argc, argv, prefix, options, mailinfo_usage, 0); diff --git a/builtin/mailsplit.c b/builtin/mailsplit.c index 41dd304731..264df6259a 100644 --- a/builtin/mailsplit.c +++ b/builtin/mailsplit.c @@ -284,6 +284,8 @@ int cmd_mailsplit(int argc, BUG_ON_NON_EMPTY_PREFIX(prefix); + show_usage_if_asked(argc, argv, git_mailsplit_usage); + for (argp = argv+1; *argp; argp++) { const char *arg = *argp; @@ -297,8 +299,6 @@ int cmd_mailsplit(int argc, continue; } else if ( arg[1] == 'f' ) { nr = strtol(arg+2, NULL, 10); - } else if ( arg[1] == 'h' ) { - usage(git_mailsplit_usage); } else if ( arg[1] == 'b' && !arg[2] ) { allow_bare = 1; } else if (!strcmp(arg, "--keep-cr")) { diff --git a/builtin/merge-base.c b/builtin/merge-base.c index a20c93b11a..123c81515e 100644 --- a/builtin/merge-base.c +++ b/builtin/merge-base.c @@ -8,7 +8,7 @@ #include "parse-options.h" #include "commit-reach.h" -static int show_merge_base(struct commit **rev, int rev_nr, int show_all) +static int show_merge_base(struct commit **rev, size_t rev_nr, int show_all) { struct commit_list *result = NULL, *r; @@ -149,7 +149,7 @@ int cmd_merge_base(int argc, struct repository *repo UNUSED) { struct commit **rev; - int rev_nr = 0; + size_t rev_nr = 0; int show_all = 0; int cmdmode = 0; int ret; diff --git a/builtin/merge-index.c b/builtin/merge-index.c index 342699edb7..3314fb1336 100644 --- a/builtin/merge-index.c +++ b/builtin/merge-index.c @@ -75,6 +75,9 @@ static void merge_all(void) } } +static const char usage_string[] = +"git merge-index [-o] [-q] <merge-program> (-a | [--] [<filename>...])"; + int cmd_merge_index(int argc, const char **argv, const char *prefix UNUSED, @@ -87,8 +90,10 @@ int cmd_merge_index(int argc, */ signal(SIGCHLD, SIG_DFL); + show_usage_if_asked(argc, argv, usage_string); + if (argc < 3) - usage("git merge-index [-o] [-q] <merge-program> (-a | [--] [<filename>...])"); + usage(usage_string); repo_read_index(the_repository); diff --git a/builtin/merge-ours.c b/builtin/merge-ours.c index 3ecd9172f1..97b8a792c7 100644 --- a/builtin/merge-ours.c +++ b/builtin/merge-ours.c @@ -23,8 +23,7 @@ int cmd_merge_ours(int argc, const char *prefix UNUSED, struct repository *repo UNUSED) { - if (argc == 2 && !strcmp(argv[1], "-h")) - usage(builtin_merge_ours_usage); + show_usage_if_asked(argc, argv, builtin_merge_ours_usage); /* * The contents of the current index becomes the tree we diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index 1dd295558b..abfc060e28 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -38,6 +38,12 @@ int cmd_merge_recursive(int argc, if (argv[0] && ends_with(argv[0], "-subtree")) o.subtree_shift = ""; + if (argc == 2 && !strcmp(argv[1], "-h")) { + struct strbuf msg = STRBUF_INIT; + strbuf_addf(&msg, builtin_merge_recursive_usage, argv[0]); + show_usage_if_asked(argc, argv, msg.buf); + } + if (argc < 4) usagef(builtin_merge_recursive_usage, argv[0]); diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 9a6c8b4e4c..3ec7127b3a 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -18,6 +18,7 @@ #include "tree.h" #include "config.h" #include "strvec.h" +#include "write-or-die.h" static int line_termination = '\n'; @@ -575,7 +576,7 @@ int cmd_merge_tree(int argc, }; /* Init merge options */ - init_ui_merge_options(&o.merge_options, the_repository); + init_basic_merge_options(&o.merge_options, the_repository); /* Parse arguments */ original_argc = argc - 1; /* ignoring argv[0] */ @@ -600,7 +601,6 @@ int cmd_merge_tree(int argc, line_termination = '\0'; while (strbuf_getline_lf(&buf, stdin) != EOF) { struct strbuf **split; - int result; const char *input_merge_base = NULL; split = strbuf_split(&buf, ' '); @@ -617,15 +617,14 @@ int cmd_merge_tree(int argc, if (input_merge_base && split[2] && split[3] && !split[4]) { strbuf_rtrim(split[2]); strbuf_rtrim(split[3]); - result = real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix); + real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix); } else if (!input_merge_base && !split[2]) { - result = real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix); + real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix); } else { die(_("malformed input line: '%s'."), buf.buf); } + maybe_flush_or_die(stdout, "stdout"); - if (result < 0) - die(_("merging cannot continue; got unclean result of %d"), result); strbuf_list_free(split); } strbuf_release(&buf); diff --git a/builtin/merge.c b/builtin/merge.c index 5f67007bba..ba9faf126a 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -1300,8 +1300,8 @@ int cmd_merge(int argc, void *branch_to_free; int orig_argc = argc; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_merge_usage, builtin_merge_options); + show_usage_with_options_if_asked(argc, argv, + builtin_merge_usage, builtin_merge_options); prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; diff --git a/builtin/notes.c b/builtin/notes.c index d051abf6df..ff61ec5f2d 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -197,7 +197,7 @@ static void prepare_note_data(const struct object_id *object, struct note_data * struct strbuf buf = STRBUF_INIT; /* write the template message before editing: */ - d->edit_path = git_pathdup("NOTES_EDITMSG"); + d->edit_path = repo_git_path(the_repository, "NOTES_EDITMSG"); fd = xopen(d->edit_path, O_CREAT | O_TRUNC | O_WRONLY, 0600); if (d->msg_nr) @@ -979,6 +979,8 @@ static int merge(int argc, const char **argv, const char *prefix, else { /* Merge has unresolved conflicts */ struct worktree **worktrees; const struct worktree *wt; + char *path; + /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */ refs_update_ref(get_main_ref_store(the_repository), msg.buf, "NOTES_MERGE_PARTIAL", &result_oid, NULL, @@ -994,10 +996,13 @@ static int merge(int argc, const char **argv, const char *prefix, if (refs_update_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", notes_ref, NULL)) die(_("failed to store link to current notes ref (%s)"), notes_ref); + + path = repo_git_path(the_repository, NOTES_MERGE_WORKTREE); fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s " "and commit the result with 'git notes merge --commit', " "or abort the merge with 'git notes merge --abort'.\n"), - git_path(NOTES_MERGE_WORKTREE)); + path); + free(path); } free_notes(t); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 1c3b842651..79e1e6fb52 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -206,6 +206,7 @@ static int have_non_local_packs; static int incremental; static int ignore_packed_keep_on_disk; static int ignore_packed_keep_in_core; +static int ignore_packed_keep_in_core_has_cruft; static int allow_ofs_delta; static struct pack_idx_option pack_idx_opts; static const char *base_name; @@ -269,6 +270,43 @@ struct configured_exclusion { static struct oidmap configured_exclusions; static struct oidset excluded_by_config; +static int name_hash_version = -1; + +/** + * Check whether the name_hash_version chosen by user input is appropriate, + * and also validate whether it is compatible with other features. + */ +static void validate_name_hash_version(void) +{ + if (name_hash_version < 1 || name_hash_version > 2) + die(_("invalid --name-hash-version option: %d"), name_hash_version); + if (write_bitmap_index && name_hash_version != 1) { + warning(_("currently, --write-bitmap-index requires --name-hash-version=1")); + name_hash_version = 1; + } +} + +static inline uint32_t pack_name_hash_fn(const char *name) +{ + static int seen_version = -1; + + if (seen_version < 0) + seen_version = name_hash_version; + else if (seen_version != name_hash_version) + BUG("name hash version changed from %d to %d mid-process", + seen_version, name_hash_version); + + switch (name_hash_version) { + case 1: + return pack_name_hash(name); + + case 2: + return pack_name_hash_v2((const unsigned char *)name); + + default: + BUG("invalid name-hash version: %d", name_hash_version); + } +} /* * stats @@ -1264,7 +1302,8 @@ static void write_pack_file(void) struct object_entry **write_order; if (progress > pack_to_stdout) - progress_state = start_progress(_("Writing objects"), nr_result); + progress_state = start_progress(the_repository, + _("Writing objects"), nr_result); ALLOC_ARRAY(written_list, to_pack.nr_objects); write_order = compute_write_order(); @@ -1318,8 +1357,9 @@ static void write_pack_file(void) */ int fd = finalize_hashfile(f, hash, FSYNC_COMPONENT_PACK, 0); - fixup_pack_header_footer(fd, hash, pack_tmp_name, - nr_written, hash, offset); + fixup_pack_header_footer(the_hash_algo, fd, hash, + pack_tmp_name, nr_written, + hash, offset); close(fd); if (write_bitmap_index) { if (write_bitmap_index != WRITE_BITMAP_QUIET) @@ -1367,9 +1407,10 @@ static void write_pack_file(void) if (cruft) pack_idx_opts.flags |= WRITE_MTIMES; - stage_tmp_packfiles(&tmpname, pack_tmp_name, - written_list, nr_written, - &to_pack, &pack_idx_opts, hash, + stage_tmp_packfiles(the_hash_algo, &tmpname, + pack_tmp_name, written_list, + nr_written, &to_pack, + &pack_idx_opts, hash, &idx_tmp_name); if (write_bitmap_index) { @@ -1462,8 +1503,60 @@ static int have_duplicate_entry(const struct object_id *oid, return 1; } +static int want_cruft_object_mtime(struct repository *r, + const struct object_id *oid, + unsigned flags, uint32_t mtime) +{ + struct packed_git **cache; + + for (cache = kept_pack_cache(r, flags); *cache; cache++) { + struct packed_git *p = *cache; + off_t ofs; + uint32_t candidate_mtime; + + ofs = find_pack_entry_one(oid, p); + if (!ofs) + continue; + + /* + * We have a copy of the object 'oid' in a non-cruft + * pack. We can avoid packing an additional copy + * regardless of what the existing copy's mtime is since + * it is outside of a cruft pack. + */ + if (!p->is_cruft) + return 0; + + /* + * If we have a copy of the object 'oid' in a cruft + * pack, then either read the cruft pack's mtime for + * that object, or, if that can't be loaded, assume the + * pack's mtime itself. + */ + if (!load_pack_mtimes(p)) { + uint32_t pos; + if (offset_to_pack_pos(p, ofs, &pos) < 0) + continue; + candidate_mtime = nth_packed_mtime(p, pos); + } else { + candidate_mtime = p->mtime; + } + + /* + * We have a surviving copy of the object in a cruft + * pack whose mtime is greater than or equal to the one + * we are considering. We can thus avoid packing an + * additional copy of that object. + */ + if (mtime <= candidate_mtime) + return 0; + } + + return -1; +} + static int want_found_object(const struct object_id *oid, int exclude, - struct packed_git *p) + struct packed_git *p, uint32_t mtime) { if (exclude) return 1; @@ -1513,12 +1606,29 @@ static int want_found_object(const struct object_id *oid, int exclude, if (ignore_packed_keep_in_core) flags |= IN_CORE_KEEP_PACKS; - if (ignore_packed_keep_on_disk && p->pack_keep) - return 0; - if (ignore_packed_keep_in_core && p->pack_keep_in_core) - return 0; - if (has_object_kept_pack(p->repo, oid, flags)) - return 0; + /* + * If the object is in a pack that we want to ignore, *and* we + * don't have any cruft packs that are being retained, we can + * abort quickly. + */ + if (!ignore_packed_keep_in_core_has_cruft) { + if (ignore_packed_keep_on_disk && p->pack_keep) + return 0; + if (ignore_packed_keep_in_core && p->pack_keep_in_core) + return 0; + if (has_object_kept_pack(p->repo, oid, flags)) + return 0; + } else { + /* + * But if there is at least one cruft pack which + * is being kept, we only want to include the + * provided object if it has a strictly greater + * mtime than any existing cruft copy. + */ + if (!want_cruft_object_mtime(p->repo, oid, flags, + mtime)) + return 0; + } } /* @@ -1537,7 +1647,8 @@ static int want_object_in_pack_one(struct packed_git *p, const struct object_id *oid, int exclude, struct packed_git **found_pack, - off_t *found_offset) + off_t *found_offset, + uint32_t found_mtime) { off_t offset; @@ -1553,7 +1664,7 @@ static int want_object_in_pack_one(struct packed_git *p, *found_offset = offset; *found_pack = p; } - return want_found_object(oid, exclude, p); + return want_found_object(oid, exclude, p, found_mtime); } return -1; } @@ -1567,10 +1678,11 @@ static int want_object_in_pack_one(struct packed_git *p, * function finds if there is any pack that has the object and returns the pack * and its offset in these variables. */ -static int want_object_in_pack(const struct object_id *oid, - int exclude, - struct packed_git **found_pack, - off_t *found_offset) +static int want_object_in_pack_mtime(const struct object_id *oid, + int exclude, + struct packed_git **found_pack, + off_t *found_offset, + uint32_t found_mtime) { int want; struct list_head *pos; @@ -1585,7 +1697,8 @@ static int want_object_in_pack(const struct object_id *oid, * are present we will determine the answer right now. */ if (*found_pack) { - want = want_found_object(oid, exclude, *found_pack); + want = want_found_object(oid, exclude, *found_pack, + found_mtime); if (want != -1) return want; @@ -1596,7 +1709,7 @@ static int want_object_in_pack(const struct object_id *oid, for (m = get_multi_pack_index(the_repository); m; m = m->next) { struct pack_entry e; if (fill_midx_entry(the_repository, oid, &e, m)) { - want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset); + want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime); if (want != -1) return want; } @@ -1604,7 +1717,7 @@ static int want_object_in_pack(const struct object_id *oid, list_for_each(pos, get_packed_git_mru(the_repository)) { struct packed_git *p = list_entry(pos, struct packed_git, mru); - want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset); + want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime); if (!exclude && want > 0) list_move(&p->mru, get_packed_git_mru(the_repository)); @@ -1634,6 +1747,15 @@ static int want_object_in_pack(const struct object_id *oid, return 1; } +static inline int want_object_in_pack(const struct object_id *oid, + int exclude, + struct packed_git **found_pack, + off_t *found_offset) +{ + return want_object_in_pack_mtime(oid, exclude, found_pack, found_offset, + 0); +} + static struct object_entry *create_object_entry(const struct object_id *oid, enum object_type type, uint32_t hash, @@ -1686,7 +1808,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, return 0; } - create_object_entry(oid, type, pack_name_hash(name), + create_object_entry(oid, type, pack_name_hash_fn(name), exclude, name && no_try_delta(name), found_pack, found_offset); return 1; @@ -1900,7 +2022,7 @@ static void add_preferred_base_object(const char *name) { struct pbase_tree *it; size_t cmplen; - unsigned hash = pack_name_hash(name); + unsigned hash = pack_name_hash_fn(name); if (!num_preferred_base || check_pbase_path(hash)) return; @@ -2400,7 +2522,8 @@ static void get_object_details(void) struct object_entry **sorted_by_offset; if (progress) - progress_state = start_progress(_("Counting objects"), + progress_state = start_progress(the_repository, + _("Counting objects"), to_pack.nr_objects); CALLOC_ARRAY(sorted_by_offset, to_pack.nr_objects); @@ -3220,7 +3343,8 @@ static void prepare_pack(int window, int depth) unsigned nr_done = 0; if (progress) - progress_state = start_progress(_("Compressing objects"), + progress_state = start_progress(the_repository, + _("Compressing objects"), nr_deltas); QSORT(delta_list, n, type_size_sort); ll_find_deltas(delta_list, n, window+1, depth, &nr_done); @@ -3410,7 +3534,7 @@ static void show_object_pack_hint(struct object *object, const char *name, * here using a now in order to perhaps improve the delta selection * process. */ - oe->hash = pack_name_hash(name); + oe->hash = pack_name_hash_fn(name); oe->no_try_delta = name && no_try_delta(name); stdin_packs_hints_nr++; @@ -3560,11 +3684,11 @@ static void add_cruft_object_entry(const struct object_id *oid, enum object_type entry = packlist_find(&to_pack, oid); if (entry) { if (name) { - entry->hash = pack_name_hash(name); + entry->hash = pack_name_hash_fn(name); entry->no_try_delta = no_try_delta(name); } } else { - if (!want_object_in_pack(oid, 0, &pack, &offset)) + if (!want_object_in_pack_mtime(oid, 0, &pack, &offset, mtime)) return; if (!pack && type == OBJ_BLOB && !has_loose_object(oid)) { /* @@ -3583,7 +3707,7 @@ static void add_cruft_object_entry(const struct object_id *oid, enum object_type return; } - entry = create_object_entry(oid, type, pack_name_hash(name), + entry = create_object_entry(oid, type, pack_name_hash_fn(name), 0, name && no_try_delta(name), pack, offset); } @@ -3638,6 +3762,8 @@ static void mark_pack_kept_in_core(struct string_list *packs, unsigned keep) struct packed_git *p = item->util; if (!p) die(_("could not find pack '%s'"), item->string); + if (p->is_cruft && keep) + ignore_packed_keep_in_core_has_cruft = 1; p->pack_keep_in_core = keep; } } @@ -3648,7 +3774,8 @@ static void add_objects_in_unpacked_packs(void); static void enumerate_cruft_objects(void) { if (progress) - progress_state = start_progress(_("Enumerating cruft objects"), 0); + progress_state = start_progress(the_repository, + _("Enumerating cruft objects"), 0); add_objects_in_unpacked_packs(); add_unreachable_loose_objects(); @@ -3674,7 +3801,8 @@ static void enumerate_and_traverse_cruft_objects(struct string_list *fresh_packs revs.ignore_missing_links = 1; if (progress) - progress_state = start_progress(_("Enumerating cruft objects"), 0); + progress_state = start_progress(the_repository, + _("Enumerating cruft objects"), 0); ret = add_unseen_recent_objects_to_traversal(&revs, cruft_expiration, set_cruft_mtime, 1); stop_progress(&progress_state); @@ -3693,7 +3821,8 @@ static void enumerate_and_traverse_cruft_objects(struct string_list *fresh_packs if (prepare_revision_walk(&revs)) die(_("revision walk setup failed")); if (progress) - progress_state = start_progress(_("Traversing cruft objects"), 0); + progress_state = start_progress(the_repository, + _("Traversing cruft objects"), 0); nr_seen = 0; traverse_commit_list(&revs, show_cruft_commit, show_cruft_object, NULL); @@ -4060,6 +4189,15 @@ static int get_object_list_from_bitmap(struct rev_info *revs) if (!(bitmap_git = prepare_bitmap_walk(revs, 0))) return -1; + /* + * For now, force the name-hash version to be 1 since that + * is the version implied by the bitmap format. Later, the + * format can include this version explicitly in its format, + * allowing readers to know the version that was used during + * the bitmap write. + */ + name_hash_version = 1; + if (pack_options_allow_reuse()) reuse_partial_packfile_from_bitmap(bitmap_git, &reuse_packfiles, @@ -4435,6 +4573,8 @@ int cmd_pack_objects(int argc, OPT_STRING_LIST(0, "uri-protocol", &uri_protocols, N_("protocol"), N_("exclude any configured uploadpack.blobpackfileuri with this protocol")), + OPT_INTEGER(0, "name-hash-version", &name_hash_version, + N_("use the specified name-hash function to group similar objects")), OPT_END(), }; @@ -4590,6 +4730,11 @@ int cmd_pack_objects(int argc, if (pack_to_stdout || !rev_list_all) write_bitmap_index = 0; + if (name_hash_version < 0) + name_hash_version = (int)git_env_ulong("GIT_TEST_NAME_HASH_VERSION", 1); + + validate_name_hash_version(); + if (use_delta_islands) strvec_push(&rp, "--topo-order"); @@ -4625,7 +4770,8 @@ int cmd_pack_objects(int argc, prepare_packing_data(the_repository, &to_pack); if (progress && !cruft) - progress_state = start_progress(_("Enumerating objects"), 0); + progress_state = start_progress(the_repository, + _("Enumerating objects"), 0); if (stdin_packs) { /* avoids adding objects in excluded packs */ ignore_packed_keep_in_core = 1; diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c index e046575871..3febe732f8 100644 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@ -595,8 +595,7 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, s struct strbuf idx_name = STRBUF_INIT; char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */ - if (argc == 2 && !strcmp(argv[1], "-h")) - usage(pack_redundant_usage); + show_usage_if_asked(argc, argv, pack_redundant_usage); for (i = 1; i < argc; i++) { const char *arg = argv[i]; diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c index 4fdd68880e..e47bae1c80 100644 --- a/builtin/pack-refs.c +++ b/builtin/pack-refs.c @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "builtin.h" #include "config.h" #include "gettext.h" @@ -15,7 +13,7 @@ static char const * const pack_refs_usage[] = { int cmd_pack_refs(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct ref_exclusions excludes = REF_EXCLUSIONS_INIT; struct string_list included_refs = STRING_LIST_INIT_NODUP; @@ -39,7 +37,7 @@ int cmd_pack_refs(int argc, N_("references to exclude")), OPT_END(), }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0)) usage_with_options(pack_refs_usage, opts); @@ -52,7 +50,7 @@ int cmd_pack_refs(int argc, if (!pack_refs_opts.includes->nr) string_list_append(pack_refs_opts.includes, "refs/tags/*"); - ret = refs_pack_refs(get_main_ref_store(the_repository), &pack_refs_opts); + ret = refs_pack_refs(get_main_ref_store(repo), &pack_refs_opts); clear_ref_exclusions(&excludes); string_list_clear(&included_refs, 0); diff --git a/builtin/patch-id.c b/builtin/patch-id.c index f540d8daa7..cdef2ec10a 100644 --- a/builtin/patch-id.c +++ b/builtin/patch-id.c @@ -70,7 +70,7 @@ static size_t get_one_patchid(struct object_id *next_oid, struct object_id *resu int before = -1, after = -1; int diff_is_binary = 0; char pre_oid_str[GIT_MAX_HEXSZ + 1], post_oid_str[GIT_MAX_HEXSZ + 1]; - git_hash_ctx ctx; + struct git_hash_ctx ctx; the_hash_algo->init_fn(&ctx); oidclr(result, the_repository->hash_algo); @@ -85,7 +85,7 @@ static size_t get_one_patchid(struct object_id *next_oid, struct object_id *resu !skip_prefix(line, "From ", &p) && starts_with(line, "\\ ") && 12 < strlen(line)) { if (verbatim) - the_hash_algo->update_fn(&ctx, line, strlen(line)); + git_hash_update(&ctx, line, strlen(line)); continue; } @@ -104,10 +104,10 @@ static size_t get_one_patchid(struct object_id *next_oid, struct object_id *resu starts_with(line, "Binary files")) { diff_is_binary = 1; before = 0; - the_hash_algo->update_fn(&ctx, pre_oid_str, - strlen(pre_oid_str)); - the_hash_algo->update_fn(&ctx, post_oid_str, - strlen(post_oid_str)); + git_hash_update(&ctx, pre_oid_str, + strlen(pre_oid_str)); + git_hash_update(&ctx, post_oid_str, + strlen(post_oid_str)); if (stable) flush_one_hunk(result, &ctx); continue; @@ -165,7 +165,7 @@ static size_t get_one_patchid(struct object_id *next_oid, struct object_id *resu /* Add line to hash algo (possibly removing whitespace) */ len = verbatim ? strlen(line) : remove_space(line); patchlen += len; - the_hash_algo->update_fn(&ctx, line, len); + git_hash_update(&ctx, line, len); } if (!found_next) diff --git a/builtin/prune.c b/builtin/prune.c index aeff9ca1b3..1c357fffd8 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -64,7 +64,8 @@ static void perform_reachability_traversal(struct rev_info *revs) return; if (show_progress) - progress = start_delayed_progress(_("Checking connectivity"), 0); + progress = start_delayed_progress(the_repository, + _("Checking connectivity"), 0); mark_reachable_objects(revs, 1, expire, progress); stop_progress(&progress); initialized = 1; diff --git a/builtin/push.c b/builtin/push.c index 90de3746b5..92d530e5c4 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -78,7 +78,7 @@ static void refspec_append_mapped(struct refspec *refspec, const char *ref, .src = matched->name, }; - if (!query_refspecs(&remote->push, &query) && query.dst) { + if (!refspec_find_match(&remote->push, &query) && query.dst) { refspec_appendf(refspec, "%s%s:%s", query.force ? "+" : "", query.src, query.dst); diff --git a/builtin/rebase.c b/builtin/rebase.c index 0498fff3c9..d4715ed35d 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -644,7 +644,7 @@ static int run_am(struct rebase_options *opts) return run_command(&am); } - rebased_patches = xstrdup(git_path("rebased-patches")); + rebased_patches = repo_git_path(the_repository, "rebased-patches"); format_patch.out = open(rebased_patches, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (format_patch.out < 0) { @@ -1223,9 +1223,9 @@ int cmd_rebase(int argc, }; int i; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_rebase_usage, - builtin_rebase_options); + show_usage_with_options_if_asked(argc, argv, + builtin_rebase_usage, + builtin_rebase_options); prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index c2e9103f11..7b28fc9df6 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -174,7 +174,7 @@ static int receive_pack_config(const char *var, const char *value, char *path; if (git_config_pathname(&path, var, value)) - return 1; + return -1; strbuf_addf(&fsck_msg_types, "%cskiplist=%s", fsck_msg_types.len ? ',' : '=', path); free(path); @@ -566,14 +566,14 @@ static void hmac_hash(unsigned char *out, unsigned char k_ipad[GIT_MAX_BLKSZ]; unsigned char k_opad[GIT_MAX_BLKSZ]; int i; - git_hash_ctx ctx; + struct git_hash_ctx ctx; /* RFC 2104 2. (1) */ memset(key, '\0', GIT_MAX_BLKSZ); if (the_hash_algo->blksz < key_len) { the_hash_algo->init_fn(&ctx); - the_hash_algo->update_fn(&ctx, key_in, key_len); - the_hash_algo->final_fn(key, &ctx); + git_hash_update(&ctx, key_in, key_len); + git_hash_final(key, &ctx); } else { memcpy(key, key_in, key_len); } @@ -586,15 +586,15 @@ static void hmac_hash(unsigned char *out, /* RFC 2104 2. (3) & (4) */ the_hash_algo->init_fn(&ctx); - the_hash_algo->update_fn(&ctx, k_ipad, sizeof(k_ipad)); - the_hash_algo->update_fn(&ctx, text, text_len); - the_hash_algo->final_fn(out, &ctx); + git_hash_update(&ctx, k_ipad, sizeof(k_ipad)); + git_hash_update(&ctx, text, text_len); + git_hash_final(out, &ctx); /* RFC 2104 2. (6) & (7) */ the_hash_algo->init_fn(&ctx); - the_hash_algo->update_fn(&ctx, k_opad, sizeof(k_opad)); - the_hash_algo->update_fn(&ctx, out, the_hash_algo->rawsz); - the_hash_algo->final_fn(out, &ctx); + git_hash_update(&ctx, k_opad, sizeof(k_opad)); + git_hash_update(&ctx, out, the_hash_algo->rawsz); + git_hash_final(out, &ctx); } static char *prepare_push_cert_nonce(const char *path, timestamp_t stamp) @@ -1435,7 +1435,8 @@ static const char *push_to_checkout(unsigned char *hash, static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree) { - const char *retval, *git_dir; + const char *retval; + char *git_dir; struct strvec env = STRVEC_INIT; int invoked_hook; @@ -1453,6 +1454,7 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w retval = push_to_deploy(sha1, &env, worktree->path); strvec_clear(&env); + free(git_dir); return retval; } @@ -2239,7 +2241,7 @@ static const char *unpack(int err_fd, struct shallow_info *si) strvec_push(&child.args, alt_shallow_file); } - tmp_objdir = tmp_objdir_create("incoming"); + tmp_objdir = tmp_objdir_create(the_repository, "incoming"); if (!tmp_objdir) { if (err_fd > 0) close(err_fd); @@ -2304,7 +2306,7 @@ static const char *unpack(int err_fd, struct shallow_info *si) if (status) return "index-pack fork failed"; - lockfile = index_pack_lockfile(child.out, NULL); + lockfile = index_pack_lockfile(the_repository, child.out, NULL); if (lockfile) { pack_lockfile = register_tempfile(lockfile); free(lockfile); @@ -2628,7 +2630,7 @@ int cmd_receive_pack(int argc, } } if (auto_update_server_info) - update_server_info(0); + update_server_info(the_repository, 0); clear_shallow_info(&si); } if (use_sideband) diff --git a/builtin/refs.c b/builtin/refs.c index a29f195834..998d2a2c1c 100644 --- a/builtin/refs.c +++ b/builtin/refs.c @@ -8,7 +8,7 @@ #include "worktree.h" #define REFS_MIGRATE_USAGE \ - N_("git refs migrate --ref-format=<format> [--dry-run]") + N_("git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]") #define REFS_VERIFY_USAGE \ N_("git refs verify [--strict] [--verbose]") @@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix, OPT_BIT(0, "dry-run", &flags, N_("perform a non-destructive dry-run"), REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN), + OPT_BIT(0, "no-reflog", &flags, + N_("drop reflogs entirely during the migration"), + REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG), OPT_END(), }; struct strbuf errbuf = STRBUF_INIT; @@ -88,7 +91,7 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix, git_config(git_fsck_config, &fsck_refs_options); prepare_repo_settings(the_repository); - worktrees = get_worktrees(); + worktrees = get_worktrees_without_reading_head(); for (size_t i = 0; worktrees[i]; i++) ret |= refs_fsck(get_worktree_ref_store(worktrees[i]), &fsck_refs_options, worktrees[i]); diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c index 33c8ae0fc7..bd2037f27d 100644 --- a/builtin/remote-ext.c +++ b/builtin/remote-ext.c @@ -202,6 +202,8 @@ int cmd_remote_ext(int argc, { BUG_ON_NON_EMPTY_PREFIX(prefix); + show_usage_if_asked(argc, argv, usage_msg); + if (argc != 3) usage(usage_msg); diff --git a/builtin/remote-fd.c b/builtin/remote-fd.c index ae896eda57..39908546ba 100644 --- a/builtin/remote-fd.c +++ b/builtin/remote-fd.c @@ -64,6 +64,7 @@ int cmd_remote_fd(int argc, BUG_ON_NON_EMPTY_PREFIX(prefix); + show_usage_if_asked(argc, argv, usage_msg); if (argc != 3) usage(usage_msg); diff --git a/builtin/remote.c b/builtin/remote.c index 0435963286..1b7aad8838 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -383,7 +383,7 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat states->remote->fetch.items[i].raw); for (ref = fetch_map; ref; ref = ref->next) { - if (omit_name_by_refspec(ref->name, &states->remote->fetch)) + if (refname_matches_negative_refspec_item(ref->name, &states->remote->fetch)) string_list_append(&states->skipped, abbrev_branch(ref->name)); else if (!ref->peer_ref || !refs_ref_exists(get_main_ref_store(the_repository), ref->peer_ref->name)) string_list_append(&states->new_refs, abbrev_branch(ref->name)); @@ -642,10 +642,14 @@ static int migrate_file(struct remote *remote) strbuf_addf(&buf, "remote.%s.fetch", remote->name); for (i = 0; i < remote->fetch.nr; i++) git_config_set_multivar(buf.buf, remote->fetch.items[i].raw, "^$", 0); +#ifndef WITH_BREAKING_CHANGES if (remote->origin == REMOTE_REMOTES) - unlink_or_warn(git_path("remotes/%s", remote->name)); + unlink_or_warn(repo_git_path_replace(the_repository, &buf, + "remotes/%s", remote->name)); else if (remote->origin == REMOTE_BRANCHES) - unlink_or_warn(git_path("branches/%s", remote->name)); + unlink_or_warn(repo_git_path_replace(the_repository, &buf, + "branches/%s", remote->name)); +#endif /* WITH_BREAKING_CHANGES */ strbuf_release(&buf); return 0; @@ -820,7 +824,8 @@ static int mv(int argc, const char **argv, const char *prefix, * Count symrefs twice, since "renaming" them is done by * deleting and recreating them in two separate passes. */ - progress = start_progress(_("Renaming remote references"), + progress = start_progress(the_repository, + _("Renaming remote references"), rename.remote_branches->nr + rename.symrefs_nr); } for (i = 0; i < remote_branches.nr; i++) { diff --git a/builtin/repack.c b/builtin/repack.c index 0c6dad7df4..75e3752353 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -41,7 +41,9 @@ static int run_update_server_info = 1; static char *packdir, *packtmp_name, *packtmp; static const char *const git_repack_usage[] = { - N_("git repack [<options>]"), + N_("git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" + "[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" + "[--write-midx] [--name-hash-version=<n>]"), NULL }; @@ -60,6 +62,7 @@ struct pack_objects_args { int no_reuse_object; int quiet; int local; + int name_hash_version; struct list_objects_filter_options filter_options; }; @@ -308,6 +311,8 @@ static void prepare_pack_objects(struct child_process *cmd, strvec_pushf(&cmd->args, "--no-reuse-delta"); if (args->no_reuse_object) strvec_pushf(&cmd->args, "--no-reuse-object"); + if (args->name_hash_version) + strvec_pushf(&cmd->args, "--name-hash-version=%d", args->name_hash_version); if (args->local) strvec_push(&cmd->args, "--local"); if (args->quiet) @@ -1205,6 +1210,8 @@ int cmd_repack(int argc, N_("pass --no-reuse-delta to git-pack-objects")), OPT_BOOL('F', NULL, &po_args.no_reuse_object, N_("pass --no-reuse-object to git-pack-objects")), + OPT_INTEGER(0, "name-hash-version", &po_args.name_hash_version, + N_("specify the name hash version to use for grouping similar objects by path")), OPT_NEGBIT('n', NULL, &run_update_server_info, N_("do not run git-update-server-info"), 1), OPT__QUIET(&po_args.quiet, N_("be quiet")), @@ -1370,9 +1377,12 @@ int cmd_repack(int argc, "--unpack-unreachable"); } else if (keep_unreachable) { strvec_push(&cmd.args, "--keep-unreachable"); - strvec_push(&cmd.args, "--pack-loose-unreachable"); } } + + if (keep_unreachable && delete_redundant && + !(pack_everything & PACK_CRUFT)) + strvec_push(&cmd.args, "--pack-loose-unreachable"); } else if (geometry.split_factor) { strvec_push(&cmd.args, "--stdin-packs"); strvec_push(&cmd.args, "--unpacked"); @@ -1565,7 +1575,7 @@ int cmd_repack(int argc, } if (run_update_server_info) - update_server_info(0); + update_server_info(the_repository, 0); if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0)) { unsigned flags = 0; diff --git a/builtin/replace.c b/builtin/replace.c index a4eaadff91..15ec0922ce 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -345,7 +345,7 @@ static int edit_and_replace(const char *object_ref, int force, int raw) } strbuf_release(&ref); - tmpfile = git_pathdup("REPLACE_EDITOBJ"); + tmpfile = repo_git_path(the_repository, "REPLACE_EDITOBJ"); if (export_object(&old_oid, type, raw, tmpfile)) { free(tmpfile); return -1; diff --git a/builtin/replay.c b/builtin/replay.c index 1afc6d1ee0..032c172b65 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -163,9 +163,10 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info, get_ref_information(cmd_info, &rinfo); if (!rinfo.positive_refexprs) die(_("need some commits to replay")); - if (onto_name && *advance_name) - die(_("--onto and --advance are incompatible")); - else if (onto_name) { + + die_for_incompatible_opt2(!!onto_name, "--onto", + !!*advance_name, "--advance"); + if (onto_name) { *onto = peel_committish(onto_name); if (rinfo.positive_refexprs < strset_get_size(&rinfo.positive_refs)) diff --git a/builtin/rerere.c b/builtin/rerere.c index 41127e24e5..1312e79d89 100644 --- a/builtin/rerere.c +++ b/builtin/rerere.c @@ -4,9 +4,9 @@ #include "config.h" #include "gettext.h" #include "parse-options.h" - -#include "string-list.h" #include "rerere.h" +#include "strbuf.h" +#include "string-list.h" #include "xdiff/xdiff.h" #include "xdiff-interface.h" #include "pathspec.h" @@ -112,15 +112,18 @@ int cmd_rerere(int argc, merge_rr.items[i].util = NULL; } } else if (!strcmp(argv[0], "diff")) { + struct strbuf buf = STRBUF_INIT; if (setup_rerere(the_repository, &merge_rr, flags | RERERE_READONLY) < 0) return 0; for (size_t i = 0; i < merge_rr.nr; i++) { const char *path = merge_rr.items[i].string; const struct rerere_id *id = merge_rr.items[i].util; - if (diff_two(rerere_path(id, "preimage"), path, path, path)) - die(_("unable to generate diff for '%s'"), rerere_path(id, NULL)); + if (diff_two(rerere_path(&buf, id, "preimage"), path, path, path)) + die(_("unable to generate diff for '%s'"), rerere_path(&buf, id, NULL)); } + + strbuf_release(&buf); } else usage_with_options(rerere_usage, options); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 3196da7b2d..bb26bee0d4 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -22,7 +22,10 @@ #include "progress.h" #include "reflog-walk.h" #include "oidset.h" +#include "oidmap.h" #include "packfile.h" +#include "quote.h" +#include "strbuf.h" static const char rev_list_usage[] = "git rev-list [<options>] <commit>... [--] [<path>...]\n" @@ -73,11 +76,17 @@ static unsigned progress_counter; static struct oidset omitted_objects; static int arg_print_omitted; /* print objects omitted by filter */ -static struct oidset missing_objects; +struct missing_objects_map_entry { + struct oidmap_entry entry; + const char *path; + unsigned type; +}; +static struct oidmap missing_objects; enum missing_action { MA_ERROR = 0, /* fail if any missing objects are encountered */ MA_ALLOW_ANY, /* silently allow ALL missing objects */ MA_PRINT, /* print ALL missing objects in special section */ + MA_PRINT_INFO, /* same as MA_PRINT but also prints missing object info */ MA_ALLOW_PROMISOR, /* silently allow all missing PROMISOR objects */ }; static enum missing_action arg_missing_action; @@ -101,7 +110,49 @@ static off_t get_object_disk_usage(struct object *obj) return size; } -static inline void finish_object__ma(struct object *obj) +static void add_missing_object_entry(struct object_id *oid, const char *path, + unsigned type) +{ + struct missing_objects_map_entry *entry; + + if (oidmap_get(&missing_objects, oid)) + return; + + CALLOC_ARRAY(entry, 1); + entry->entry.oid = *oid; + entry->type = type; + if (path) + entry->path = xstrdup(path); + oidmap_put(&missing_objects, entry); +} + +static void print_missing_object(struct missing_objects_map_entry *entry, + int print_missing_info) +{ + struct strbuf sb = STRBUF_INIT; + + if (!print_missing_info) { + printf("?%s\n", oid_to_hex(&entry->entry.oid)); + return; + } + + if (entry->path && *entry->path) { + struct strbuf path = STRBUF_INIT; + + strbuf_addstr(&sb, " path="); + quote_path(entry->path, NULL, &path, QUOTE_PATH_QUOTE_SP); + strbuf_addbuf(&sb, &path); + + strbuf_release(&path); + } + if (entry->type) + strbuf_addf(&sb, " type=%s", type_name(entry->type)); + + printf("?%s%s\n", oid_to_hex(&entry->entry.oid), sb.buf); + strbuf_release(&sb); +} + +static inline void finish_object__ma(struct object *obj, const char *name) { /* * Whether or not we try to dynamically fetch missing objects @@ -119,7 +170,8 @@ static inline void finish_object__ma(struct object *obj) return; case MA_PRINT: - oidset_insert(&missing_objects, &obj->oid); + case MA_PRINT_INFO: + add_missing_object_entry(&obj->oid, name, obj->type); return; case MA_ALLOW_PROMISOR: @@ -152,7 +204,7 @@ static void show_commit(struct commit *commit, void *data) if (revs->do_not_die_on_missing_objects && oidset_contains(&revs->missing_commits, &commit->object.oid)) { - finish_object__ma(&commit->object); + finish_object__ma(&commit->object, NULL); return; } @@ -268,12 +320,11 @@ static void show_commit(struct commit *commit, void *data) finish_commit(commit); } -static int finish_object(struct object *obj, const char *name UNUSED, - void *cb_data) +static int finish_object(struct object *obj, const char *name, void *cb_data) { struct rev_list_info *info = cb_data; if (oid_object_info_extended(the_repository, &obj->oid, NULL, 0) < 0) { - finish_object__ma(obj); + finish_object__ma(obj, name); return 1; } if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT) @@ -414,6 +465,12 @@ static inline int parse_missing_action_value(const char *value) return 1; } + if (!strcmp(value, "print-info")) { + arg_missing_action = MA_PRINT_INFO; + fetch_if_missing = 0; + return 1; + } + if (!strcmp(value, "allow-promisor")) { arg_missing_action = MA_ALLOW_PROMISOR; fetch_if_missing = 0; @@ -542,8 +599,7 @@ int cmd_rev_list(int argc, const char *show_progress = NULL; int ret = 0; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage(rev_list_usage); + show_usage_if_asked(argc, argv, rev_list_usage); git_config(git_default_config, NULL); repo_init_revisions(the_repository, &revs, prefix); @@ -735,7 +791,8 @@ int cmd_rev_list(int argc, revs.limited = 1; if (show_progress) - progress = start_delayed_progress(show_progress, 0); + progress = start_delayed_progress(the_repository, + show_progress, 0); if (use_bitmap_index) { if (!try_bitmap_count(&revs, filter_provided_objects)) @@ -781,10 +838,18 @@ int cmd_rev_list(int argc, if (arg_print_omitted) oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE); - if (arg_missing_action == MA_PRINT) { - oidset_init(&missing_objects, DEFAULT_OIDSET_SIZE); + if (arg_missing_action == MA_PRINT || + arg_missing_action == MA_PRINT_INFO) { + struct oidset_iter iter; + struct object_id *oid; + + oidmap_init(&missing_objects, DEFAULT_OIDSET_SIZE); + oidset_iter_init(&revs.missing_commits, &iter); + /* Add missing tips */ - oidset_insert_from_set(&missing_objects, &revs.missing_commits); + while ((oid = oidset_iter_next(&iter))) + add_missing_object_entry(oid, NULL, 0); + oidset_clear(&revs.missing_commits); } @@ -800,13 +865,20 @@ int cmd_rev_list(int argc, printf("~%s\n", oid_to_hex(oid)); oidset_clear(&omitted_objects); } - if (arg_missing_action == MA_PRINT) { - struct oidset_iter iter; - struct object_id *oid; - oidset_iter_init(&missing_objects, &iter); - while ((oid = oidset_iter_next(&iter))) - printf("?%s\n", oid_to_hex(oid)); - oidset_clear(&missing_objects); + if (arg_missing_action == MA_PRINT || + arg_missing_action == MA_PRINT_INFO) { + struct missing_objects_map_entry *entry; + struct oidmap_iter iter; + + oidmap_iter_init(&missing_objects, &iter); + + while ((entry = oidmap_iter_next(&iter))) { + print_missing_object(entry, arg_missing_action == + MA_PRINT_INFO); + free((void *)entry->path); + } + + oidmap_free(&missing_objects, true); } stop_progress(&progress); diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 949747a6b6..490da33bec 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -713,6 +713,8 @@ int cmd_rev_parse(int argc, int seen_end_of_options = 0; enum format_type format = FORMAT_DEFAULT; + show_usage_if_asked(argc, argv, builtin_rev_parse_usage); + if (argc > 1 && !strcmp("--parseopt", argv[1])) return cmd_parseopt(argc - 1, argv + 1, prefix); @@ -787,8 +789,8 @@ int cmd_rev_parse(int argc, if (!strcmp(arg, "--git-path")) { if (!argv[i + 1]) die(_("--git-path requires an argument")); - strbuf_reset(&buf); - print_path(git_path("%s", argv[i + 1]), prefix, + print_path(repo_git_path_replace(the_repository, &buf, + "%s", argv[i + 1]), prefix, format, DEFAULT_RELATIVE_IF_SHARED); i++; @@ -1081,7 +1083,7 @@ int cmd_rev_parse(int argc, die(_("Could not read the index")); if (the_repository->index->split_index) { const struct object_id *oid = &the_repository->index->split_index->base_oid; - const char *path = git_path("sharedindex.%s", oid_to_hex(oid)); + const char *path = repo_git_path_replace(the_repository, &buf, "sharedindex.%s", oid_to_hex(oid)); print_path(path, prefix, format, DEFAULT_RELATIVE); } continue; diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 59b626aae8..c6e0e9d051 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "hex.h" @@ -151,7 +150,7 @@ static int send_pack_config(const char *k, const char *v, int cmd_send_pack(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct refspec rs = REFSPEC_INIT_PUSH; const char *remote_name = NULL; @@ -212,7 +211,7 @@ int cmd_send_pack(int argc, OPT_END() }; - git_config(send_pack_config, NULL); + repo_config(repo, send_pack_config, NULL); argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0); if (argc > 0) { dest = argv[0]; @@ -317,7 +316,7 @@ int cmd_send_pack(int argc, set_ref_status_for_push(remote_refs, args.send_mirror, args.force_update); - ret = send_pack(&args, fd, conn, remote_refs, &extra_have); + ret = send_pack(repo, &args, fd, conn, remote_refs, &extra_have); if (helper_status) print_helper_status(remote_refs); diff --git a/builtin/show-index.c b/builtin/show-index.c index 756d632b51..9d4ecf5e7b 100644 --- a/builtin/show-index.c +++ b/builtin/show-index.c @@ -9,7 +9,7 @@ #include "parse-options.h" static const char *const show_index_usage[] = { - "git show-index [--object-format=<hash-algorithm>]", + "git show-index [--object-format=<hash-algorithm>] < <pack-idx-file>", NULL }; diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index f9b970f8a6..c1a8029714 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1301,7 +1301,7 @@ static void sync_submodule(const char *path, const char *prefix, remote_key = xstrfmt("remote.%s.url", default_remote); free(default_remote); - submodule_to_gitdir(&sb, path); + submodule_to_gitdir(the_repository, &sb, path); strbuf_addstr(&sb, "/config"); if (git_config_set_in_file_gently(sb.buf, remote_key, NULL, sub_origin_url)) @@ -1826,7 +1826,7 @@ static int clone_submodule(const struct module_clone_data *clone_data, connect_work_tree_and_git_dir(clone_data_path, sm_gitdir, 0); - p = git_pathdup_submodule(clone_data_path, "config"); + p = repo_submodule_path(the_repository, clone_data_path, "config"); if (!p) die(_("could not get submodule directory for '%s'"), clone_data_path); diff --git a/builtin/tag.c b/builtin/tag.c index c4bd145831..d3e0943b73 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -667,7 +667,7 @@ int cmd_tag(int argc, if (create_tag_object) { if (force_sign_annotate && !annotate) opt.sign = 1; - path = git_pathdup("TAG_EDITMSG"); + path = repo_git_path(the_repository, "TAG_EDITMSG"); create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object, &trailer_args, path); } @@ -698,7 +698,6 @@ int cmd_tag(int argc, cleanup: ref_sorting_release(sorting); ref_filter_clear(&filter); - ref_format_clear(&format); strbuf_release(&buf); strbuf_release(&ref); strbuf_release(&reflog_msg); diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c index 6da2825753..fb5fcbc40a 100644 --- a/builtin/unpack-file.c +++ b/builtin/unpack-file.c @@ -26,6 +26,9 @@ static char *create_temp_file(struct object_id *oid) return path; } +static const char usage_msg[] = +"git unpack-file <blob>"; + int cmd_unpack_file(int argc, const char **argv, const char *prefix UNUSED, @@ -33,8 +36,9 @@ int cmd_unpack_file(int argc, { struct object_id oid; - if (argc != 2 || !strcmp(argv[1], "-h")) - usage("git unpack-file <blob>"); + show_usage_if_asked(argc, argv, usage_msg); + if (argc != 2) + usage(usage_msg); if (repo_get_oid(the_repository, argv[1], &oid)) die("Not a valid object name %s", argv[1]); diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 2197d6d933..8383bcf404 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -18,6 +18,7 @@ #include "progress.h" #include "decorate.h" #include "fsck.h" +#include "packfile.h" static int dry_run, quiet, recover, has_errors, strict; static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict]"; @@ -27,7 +28,7 @@ static unsigned char buffer[4096]; static unsigned int offset, len; static off_t consumed_bytes; static off_t max_input_size; -static git_hash_ctx ctx; +static struct git_hash_ctx ctx; static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; static struct progress *progress; @@ -69,7 +70,7 @@ static void *fill(int min) if (min > sizeof(buffer)) die("cannot fill %d bytes", min); if (offset) { - the_hash_algo->update_fn(&ctx, buffer, offset); + git_hash_update(&ctx, buffer, offset); memmove(buffer, buffer + offset, len); offset = 0; } @@ -578,19 +579,21 @@ static void unpack_one(unsigned nr) static void unpack_all(void) { int i; - struct pack_header *hdr = fill(sizeof(struct pack_header)); + unsigned char *hdr = fill(sizeof(struct pack_header)); - nr_objects = ntohl(hdr->hdr_entries); - - if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE) + if (get_be32(hdr) != PACK_SIGNATURE) die("bad pack file"); - if (!pack_version_ok(hdr->hdr_version)) + hdr += 4; + if (!pack_version_ok_native(get_be32(hdr))) die("unknown pack file version %"PRIu32, - ntohl(hdr->hdr_version)); + get_be32(hdr)); + hdr += 4; + nr_objects = get_be32(hdr); use(sizeof(struct pack_header)); if (!quiet) - progress = start_progress(_("Unpacking objects"), nr_objects); + progress = start_progress(the_repository, + _("Unpacking objects"), nr_objects); CALLOC_ARRAY(obj_list, nr_objects); begin_odb_transaction(); for (i = 0; i < nr_objects; i++) { @@ -611,7 +614,7 @@ int cmd_unpack_objects(int argc, { int i; struct object_id oid; - git_hash_ctx tmp_ctx; + struct git_hash_ctx tmp_ctx; disable_replace_refs(); @@ -619,6 +622,8 @@ int cmd_unpack_objects(int argc, quiet = !isatty(2); + show_usage_if_asked(argc, argv, unpack_usage); + for (i = 1 ; i < argc; i++) { const char *arg = argv[i]; @@ -644,19 +649,10 @@ int cmd_unpack_objects(int argc, fsck_set_msg_types(&fsck_options, arg); continue; } - if (starts_with(arg, "--pack_header=")) { - struct pack_header *hdr; - char *c; - - hdr = (struct pack_header *)buffer; - hdr->hdr_signature = htonl(PACK_SIGNATURE); - hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10)); - if (*c != ',') - die("bad %s", arg); - hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10)); - if (*c) - die("bad %s", arg); - len = sizeof(*hdr); + if (skip_prefix(arg, "--pack_header=", &arg)) { + if (parse_pack_header_option(arg, + buffer, &len) < 0) + die(_("bad --pack_header: %s"), arg); continue; } if (skip_prefix(arg, "--max-input-size=", &arg)) { @@ -671,10 +667,9 @@ int cmd_unpack_objects(int argc, } the_hash_algo->init_fn(&ctx); unpack_all(); - the_hash_algo->update_fn(&ctx, buffer, offset); - the_hash_algo->init_fn(&tmp_ctx); - the_hash_algo->clone_fn(&tmp_ctx, &ctx); - the_hash_algo->final_oid_fn(&oid, &tmp_ctx); + git_hash_update(&ctx, buffer, offset); + git_hash_clone(&tmp_ctx, &ctx); + git_hash_final_oid(&oid, &tmp_ctx); if (strict) { write_rest(); if (fsck_finish(&fsck_options)) diff --git a/builtin/update-index.c b/builtin/update-index.c index 74bbad9f87..b2f6b1a3fb 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -1045,8 +1045,8 @@ int cmd_update_index(int argc, OPT_END() }; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(update_index_usage, options); + show_usage_with_options_if_asked(argc, argv, + update_index_usage, options); git_config(git_default_config, NULL); diff --git a/builtin/update-ref.c b/builtin/update-ref.c index 4d35bdc4b4..1d541e13ad 100644 --- a/builtin/update-ref.c +++ b/builtin/update-ref.c @@ -179,7 +179,8 @@ static int parse_next_oid(const char **next, const char *end, (*next)++; *next = parse_arg(*next, &arg); if (arg.len) { - if (repo_get_oid(the_repository, arg.buf, oid)) + if (repo_get_oid_with_flags(the_repository, arg.buf, oid, + GET_OID_SKIP_AMBIGUITY_CHECK)) goto invalid; } else { /* Without -z, an empty value means all zeros: */ @@ -197,7 +198,8 @@ static int parse_next_oid(const char **next, const char *end, *next += arg.len; if (arg.len) { - if (repo_get_oid(the_repository, arg.buf, oid)) + if (repo_get_oid_with_flags(the_repository, arg.buf, oid, + GET_OID_SKIP_AMBIGUITY_CHECK)) goto invalid; } else if (flags & PARSE_SHA1_ALLOW_EMPTY) { /* With -z, treat an empty value as all zeros: */ @@ -299,7 +301,8 @@ static void parse_cmd_symref_update(struct ref_transaction *transaction, die("symref-update %s: expected old value", refname); if (!strcmp(old_arg, "oid")) { - if (repo_get_oid(the_repository, old_target, &old_oid)) + if (repo_get_oid_with_flags(the_repository, old_target, &old_oid, + GET_OID_SKIP_AMBIGUITY_CHECK)) die("symref-update %s: invalid oid: %s", refname, old_target); have_old_oid = 1; @@ -772,7 +775,8 @@ int cmd_update_ref(int argc, refname = argv[0]; value = argv[1]; oldval = argv[2]; - if (repo_get_oid(the_repository, value, &oid)) + if (repo_get_oid_with_flags(the_repository, value, &oid, + GET_OID_SKIP_AMBIGUITY_CHECK)) die("%s: not a valid SHA1", value); } @@ -783,7 +787,8 @@ int cmd_update_ref(int argc, * must not already exist: */ oidclr(&oldoid, the_repository->hash_algo); - else if (repo_get_oid(the_repository, oldval, &oldoid)) + else if (repo_get_oid_with_flags(the_repository, oldval, &oldoid, + GET_OID_SKIP_AMBIGUITY_CHECK)) die("%s: not a valid old SHA1", oldval); } diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c index 6769611a02..d7467290a8 100644 --- a/builtin/update-server-info.c +++ b/builtin/update-server-info.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -13,7 +12,7 @@ static const char * const update_server_info_usage[] = { int cmd_update_server_info(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int force = 0; struct option options[] = { @@ -21,11 +20,12 @@ int cmd_update_server_info(int argc, OPT_END() }; - git_config(git_default_config, NULL); + if (repo) + repo_config(repo, git_default_config, NULL); argc = parse_options(argc, argv, prefix, options, update_server_info_usage, 0); if (argc > 0) usage_with_options(update_server_info_usage, options); - return !!update_server_info(force); + return !!update_server_info(repo, force); } diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c index 9e9343f121..97d7c9522f 100644 --- a/builtin/upload-archive.c +++ b/builtin/upload-archive.c @@ -27,7 +27,8 @@ int cmd_upload_archive_writer(int argc, const char *arg_cmd = "argument "; int ret; - if (argc != 2 || !strcmp(argv[1], "-h")) + show_usage_if_asked(argc, argv, upload_archive_usage); + if (argc != 2) usage(upload_archive_usage); if (!enter_repo(argv[1], 0)) @@ -92,8 +93,7 @@ struct repository *repo UNUSED) BUG_ON_NON_EMPTY_PREFIX(prefix); - if (argc == 2 && !strcmp(argv[1], "-h")) - usage(upload_archive_usage); + show_usage_if_asked(argc, argv, upload_archive_usage); /* * Set up sideband subprocess. diff --git a/builtin/upload-pack.c b/builtin/upload-pack.c index dd63d6eadf..c2bbc035ab 100644 --- a/builtin/upload-pack.c +++ b/builtin/upload-pack.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "builtin.h" #include "exec-cmd.h" #include "gettext.h" @@ -63,9 +65,9 @@ int cmd_upload_pack(int argc, switch (determine_protocol_version_server()) { case protocol_v2: if (advertise_refs) - protocol_v2_advertise_capabilities(); + protocol_v2_advertise_capabilities(the_repository); else - protocol_v2_serve_loop(stateless_rpc); + protocol_v2_serve_loop(the_repository, stateless_rpc); break; case protocol_v1: /* diff --git a/builtin/var.c b/builtin/var.c index 1449656cc9..ada642a9fe 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -42,7 +42,7 @@ static char *sequence_editor(int ident_flag UNUSED) static char *pager(int ident_flag UNUSED) { - const char *pgm = git_pager(1); + const char *pgm = git_pager(the_repository, 1); if (!pgm) pgm = "cat"; @@ -221,6 +221,7 @@ int cmd_var(int argc, const struct git_var *git_var; char *val; + show_usage_if_asked(argc, argv, var_usage); if (argc != 2) usage(var_usage); diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c index 779b7988ca..5f749a30da 100644 --- a/builtin/verify-commit.c +++ b/builtin/verify-commit.c @@ -5,7 +5,6 @@ * * Based on git-verify-tag */ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -33,15 +32,15 @@ static int run_gpg_verify(struct commit *commit, unsigned flags) return ret; } -static int verify_commit(const char *name, unsigned flags) +static int verify_commit(struct repository *repo, const char *name, unsigned flags) { struct object_id oid; struct object *obj; - if (repo_get_oid(the_repository, name, &oid)) + if (repo_get_oid(repo, name, &oid)) return error("commit '%s' not found.", name); - obj = parse_object(the_repository, &oid); + obj = parse_object(repo, &oid); if (!obj) return error("%s: unable to read file.", name); if (obj->type != OBJ_COMMIT) @@ -54,7 +53,7 @@ static int verify_commit(const char *name, unsigned flags) int cmd_verify_commit(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; @@ -64,7 +63,7 @@ int cmd_verify_commit(int argc, OPT_END() }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); argc = parse_options(argc, argv, prefix, verify_commit_options, verify_commit_usage, PARSE_OPT_KEEP_ARGV0); @@ -78,7 +77,7 @@ int cmd_verify_commit(int argc, * was received in the process of writing the gpg input: */ signal(SIGPIPE, SIG_IGN); while (i < argc) - if (verify_commit(argv[i++], flags)) + if (verify_commit(repo, argv[i++], flags)) had_error = 1; return had_error; } diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index a7f20618ff..ed1c40338f 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -5,7 +5,6 @@ * * Based on git-verify-tag.sh */ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -23,7 +22,7 @@ static const char * const verify_tag_usage[] = { int cmd_verify_tag(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; @@ -35,7 +34,7 @@ int cmd_verify_tag(int argc, OPT_END() }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); argc = parse_options(argc, argv, prefix, verify_tag_options, verify_tag_usage, PARSE_OPT_KEEP_ARGV0); @@ -56,7 +55,7 @@ int cmd_verify_tag(int argc, struct object_id oid; const char *name = argv[i++]; - if (repo_get_oid(the_repository, name, &oid)) { + if (repo_get_oid(repo, name, &oid)) { had_error = !!error("tag '%s' not found.", name); continue; } @@ -69,6 +68,5 @@ int cmd_verify_tag(int argc, if (format.format) pretty_print_ref(name, &oid, &format); } - ref_format_clear(&format); return had_error; } diff --git a/builtin/worktree.c b/builtin/worktree.c index c043d4d523..48448a8355 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -151,7 +151,7 @@ static int delete_git_dir(const char *id) struct strbuf sb = STRBUF_INIT; int ret; - strbuf_addstr(&sb, git_common_path("worktrees/%s", id)); + repo_common_path_append(the_repository, &sb, "worktrees/%s", id); ret = remove_dir_recursively(&sb, 0); if (ret < 0 && errno == ENOTDIR) ret = unlink(sb.buf); @@ -163,7 +163,9 @@ static int delete_git_dir(const char *id) static void delete_worktrees_dir_if_empty(void) { - rmdir(git_path("worktrees")); /* ignore failed removal */ + char *path = repo_git_path(the_repository, "worktrees"); + rmdir(path); /* ignore failed removal */ + free(path); } static void prune_worktree(const char *id, const char *reason) @@ -212,8 +214,13 @@ static void prune_worktrees(void) struct strbuf reason = STRBUF_INIT; struct strbuf main_path = STRBUF_INIT; struct string_list kept = STRING_LIST_INIT_DUP; - DIR *dir = opendir(git_path("worktrees")); + char *path; + DIR *dir; struct dirent *d; + + path = repo_git_path(the_repository, "worktrees"); + dir = opendir(path); + free(path); if (!dir) return; while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) { @@ -337,7 +344,7 @@ static void check_candidate_path(const char *path, static void copy_sparse_checkout(const char *worktree_git_dir) { - char *from_file = git_pathdup("info/sparse-checkout"); + char *from_file = repo_git_path(the_repository, "info/sparse-checkout"); char *to_file = xstrfmt("%s/info/sparse-checkout", worktree_git_dir); if (file_exists(from_file)) { @@ -353,7 +360,7 @@ static void copy_sparse_checkout(const char *worktree_git_dir) static void copy_filtered_worktree_config(const char *worktree_git_dir) { - char *from_file = git_pathdup("config.worktree"); + char *from_file = repo_git_path(the_repository, "config.worktree"); char *to_file = xstrfmt("%s/config.worktree", worktree_git_dir); if (file_exists(from_file)) { @@ -457,7 +464,7 @@ static int add_worktree(const char *path, const char *refname, BUG("How come '%s' becomes empty after sanitization?", sb.buf); strbuf_reset(&sb); name = sb_name.buf; - git_path_buf(&sb_repo, "worktrees/%s", name); + repo_git_path_replace(the_repository, &sb_repo, "worktrees/%s", name); len = sb_repo.len; if (safe_create_leading_directories_const(sb_repo.buf)) die_errno(_("could not create leading directories of '%s'"), @@ -657,8 +664,9 @@ static int can_use_local_refs(const struct add_opts *opts) if (!opts->quiet) { struct strbuf path = STRBUF_INIT; struct strbuf contents = STRBUF_INIT; + char *wt_gitdir = get_worktree_git_dir(NULL); - strbuf_add_real_path(&path, get_worktree_git_dir(NULL)); + strbuf_add_real_path(&path, wt_gitdir); strbuf_addstr(&path, "/HEAD"); strbuf_read_file(&contents, path.buf, 64); strbuf_stripspace(&contents, NULL); @@ -670,6 +678,7 @@ static int can_use_local_refs(const struct add_opts *opts) path.buf, contents.buf); strbuf_release(&path); strbuf_release(&contents); + free(wt_gitdir); } return 1; } @@ -1100,6 +1109,7 @@ static int lock_worktree(int ac, const char **av, const char *prefix, OPT_END() }; struct worktree **worktrees, *wt; + char *path; ac = parse_options(ac, av, prefix, options, git_worktree_lock_usage, 0); if (ac != 1) @@ -1120,9 +1130,11 @@ static int lock_worktree(int ac, const char **av, const char *prefix, die(_("'%s' is already locked"), av[0]); } - write_file(git_common_path("worktrees/%s/locked", wt->id), - "%s", reason); + path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id); + write_file(path, "%s", reason); + free_worktrees(worktrees); + free(path); return 0; } @@ -1133,6 +1145,7 @@ static int unlock_worktree(int ac, const char **av, const char *prefix, OPT_END() }; struct worktree **worktrees, *wt; + char *path; int ret; ac = parse_options(ac, av, prefix, options, git_worktree_unlock_usage, 0); @@ -1147,8 +1160,12 @@ static int unlock_worktree(int ac, const char **av, const char *prefix, die(_("The main working tree cannot be locked or unlocked")); if (!worktree_lock_reason(wt)) die(_("'%s' is not locked"), av[0]); - ret = unlink_or_warn(git_common_path("worktrees/%s/locked", wt->id)); + + path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id); + ret = unlink_or_warn(path); + free_worktrees(worktrees); + free(path); return ret; } @@ -1157,6 +1174,9 @@ static void validate_no_submodules(const struct worktree *wt) struct index_state istate = INDEX_STATE_INIT(the_repository); struct strbuf path = STRBUF_INIT; int i, found_submodules = 0; + char *wt_gitdir; + + wt_gitdir = get_worktree_git_dir(wt); if (is_directory(worktree_git_path(the_repository, wt, "modules"))) { /* @@ -1166,7 +1186,7 @@ static void validate_no_submodules(const struct worktree *wt) */ found_submodules = 1; } else if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"), - get_worktree_git_dir(wt)) > 0) { + wt_gitdir) > 0) { for (i = 0; i < istate.cache_nr; i++) { struct cache_entry *ce = istate.cache[i]; int err; @@ -1185,6 +1205,7 @@ static void validate_no_submodules(const struct worktree *wt) } discard_index(&istate); strbuf_release(&path); + free(wt_gitdir); if (found_submodules) die(_("working trees containing submodules cannot be moved or removed")); diff --git a/bulk-checkin.c b/bulk-checkin.c index 433070a3bd..20f2da67b9 100644 --- a/bulk-checkin.c +++ b/bulk-checkin.c @@ -44,8 +44,9 @@ static void finish_tmp_packfile(struct strbuf *basename, { char *idx_tmp_name = NULL; - stage_tmp_packfiles(basename, pack_tmp_name, written_list, nr_written, - NULL, pack_idx_opts, hash, &idx_tmp_name); + stage_tmp_packfiles(the_hash_algo, basename, pack_tmp_name, + written_list, nr_written, NULL, pack_idx_opts, hash, + &idx_tmp_name); rename_tmp_packfile_idx(basename, &idx_tmp_name); free(idx_tmp_name); @@ -70,7 +71,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state) CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE); } else { int fd = finalize_hashfile(state->f, hash, FSYNC_COMPONENT_PACK, 0); - fixup_pack_header_footer(fd, hash, state->pack_tmp_name, + fixup_pack_header_footer(the_hash_algo, fd, hash, state->pack_tmp_name, state->nr_written, hash, state->offset); close(fd); @@ -161,7 +162,7 @@ static int already_written(struct bulk_checkin_packfile *state, struct object_id * with a new pack. */ static int stream_blob_to_pack(struct bulk_checkin_packfile *state, - git_hash_ctx *ctx, off_t *already_hashed_to, + struct git_hash_ctx *ctx, off_t *already_hashed_to, int fd, size_t size, const char *path, unsigned flags) { @@ -194,7 +195,7 @@ static int stream_blob_to_pack(struct bulk_checkin_packfile *state, if (rsize < hsize) hsize = rsize; if (hsize) - the_hash_algo->update_fn(ctx, ibuf, hsize); + git_hash_update(ctx, ibuf, hsize); *already_hashed_to = offset; } s.next_in = ibuf; @@ -258,10 +259,10 @@ static int deflate_blob_to_pack(struct bulk_checkin_packfile *state, const char *path, unsigned flags) { off_t seekback, already_hashed_to; - git_hash_ctx ctx; + struct git_hash_ctx ctx; unsigned char obuf[16384]; unsigned header_len; - struct hashfile_checkpoint checkpoint = {0}; + struct hashfile_checkpoint checkpoint; struct pack_idx_entry *idx = NULL; seekback = lseek(fd, 0, SEEK_CUR); @@ -271,13 +272,16 @@ static int deflate_blob_to_pack(struct bulk_checkin_packfile *state, header_len = format_object_header((char *)obuf, sizeof(obuf), OBJ_BLOB, size); the_hash_algo->init_fn(&ctx); - the_hash_algo->update_fn(&ctx, obuf, header_len); - the_hash_algo->unsafe_init_fn(&checkpoint.ctx); + git_hash_update(&ctx, obuf, header_len); /* Note: idx is non-NULL when we are writing */ - if ((flags & HASH_WRITE_OBJECT) != 0) + if ((flags & HASH_WRITE_OBJECT) != 0) { CALLOC_ARRAY(idx, 1); + prepare_to_stream(state, flags); + hashfile_checkpoint_init(state->f, &checkpoint); + } + already_hashed_to = 0; while (1) { @@ -303,7 +307,7 @@ static int deflate_blob_to_pack(struct bulk_checkin_packfile *state, if (lseek(fd, seekback, SEEK_SET) == (off_t) -1) return error("cannot seek back"); } - the_hash_algo->final_oid_fn(result_oid, &ctx); + git_hash_final_oid(result_oid, &ctx); if (!idx) return 0; @@ -333,7 +337,7 @@ void prepare_loose_object_bulk_checkin(void) if (!odb_transaction_nesting || bulk_fsync_objdir) return; - bulk_fsync_objdir = tmp_objdir_create("bulk-fsync"); + bulk_fsync_objdir = tmp_objdir_create(the_repository, "bulk-fsync"); if (bulk_fsync_objdir) tmp_objdir_replace_primary_odb(bulk_fsync_objdir, 0); } @@ -607,8 +607,10 @@ int unbundle(struct repository *r, struct bundle_header *header, if (!opts) opts = &opts_fallback; - if (verify_bundle(r, header, opts->flags)) + if (verify_bundle(r, header, opts->flags)) { + close(bundle_fd); return -1; + } strvec_pushl(&ip.args, "index-pack", "--fix-thin", "--stdin", NULL); @@ -62,6 +62,8 @@ struct unbundle_opts { * * Before unbundling, this method will call verify_bundle() with 'flags' * provided in 'opts'. + * + * Note that the `bundle_fd` will be closed as part of the operation. */ int unbundle(struct repository *r, struct bundle_header *header, int bundle_fd, struct strvec *extra_index_pack_args, diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh index d1cb9fa878..0df74610d0 100755 --- a/ci/install-dependencies.sh +++ b/ci/install-dependencies.sh @@ -24,16 +24,16 @@ fi case "$distro" in alpine-*) - apk add --update shadow sudo build-base curl-dev openssl-dev expat-dev gettext \ - pcre2-dev python3 musl-libintl perl-utils ncurses \ + apk add --update shadow sudo meson ninja-build gcc libc-dev curl-dev openssl-dev expat-dev gettext \ + zlib-ng-dev pcre2-dev python3 musl-libintl perl-utils ncurses \ apache2 apache2-http2 apache2-proxy apache2-ssl apache2-webdav apr-util-dbd_sqlite3 \ bash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null ;; fedora-*|almalinux-*) dnf -yq update >/dev/null && - dnf -yq install make gcc findutils diffutils perl python3 gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null + dnf -yq install shadow-utils sudo make gcc findutils diffutils perl python3 gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null ;; -ubuntu-*|ubuntu32-*|debian-*) +ubuntu-*|i386/ubuntu-*|debian-*) # Required so that apt doesn't wait for user input on certain packages. export DEBIAN_FRONTEND=noninteractive @@ -42,7 +42,7 @@ ubuntu-*|ubuntu32-*|debian-*) SVN='libsvn-perl subversion' LANGUAGES='language-pack-is' ;; - ubuntu32-*) + i386/ubuntu-*) SVN= LANGUAGES='language-pack-is' ;; @@ -58,7 +58,7 @@ ubuntu-*|ubuntu32-*|debian-*) make libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \ tcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \ libemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \ - libpcre2-dev meson ninja-build pkg-config \ + libsecret-1-dev libpcre2-dev meson ninja-build pkg-config \ ${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE case "$distro" in @@ -206,26 +206,7 @@ export TERM=${TERM:-dumb} # Clear MAKEFLAGS that may come from the outside world. export MAKEFLAGS= -if test -n "$SYSTEM_COLLECTIONURI" || test -n "$SYSTEM_TASKDEFINITIONSURI" -then - CI_TYPE=azure-pipelines - # We are running in Azure Pipelines - CI_BRANCH="$BUILD_SOURCEBRANCH" - CI_COMMIT="$BUILD_SOURCEVERSION" - CI_JOB_ID="$BUILD_BUILDID" - CI_JOB_NUMBER="$BUILD_BUILDNUMBER" - CI_OS_NAME="$(echo "$AGENT_OS" | tr A-Z a-z)" - test darwin != "$CI_OS_NAME" || CI_OS_NAME=osx - CI_REPO_SLUG="$(expr "$BUILD_REPOSITORY_URI" : '.*/\([^/]*/[^/]*\)$')" - CC="${CC:-gcc}" - - # use a subdirectory of the cache dir (because the file share is shared - # among *all* phases) - cache_dir="$HOME/test-cache/$SYSTEM_PHASENAME" - - GIT_TEST_OPTS="--write-junit-xml" - JOBS=10 -elif test true = "$GITHUB_ACTIONS" +if test true = "$GITHUB_ACTIONS" then CI_TYPE=github-actions CI_BRANCH="$GITHUB_REF" @@ -246,6 +227,8 @@ then GIT_TEST_OPTS="--github-workflow-markup" JOBS=10 + + distro=$(echo "$CI_JOB_IMAGE" | tr : -) elif test true = "$GITLAB_CI" then CI_TYPE=gitlab-ci @@ -267,7 +250,7 @@ then CI_OS_NAME=osx JOBS=$(nproc) ;; - *,alpine:*|*,fedora:*|*,ubuntu:*) + *,alpine:*|*,fedora:*|*,ubuntu:*|*,i386/ubuntu:*) CI_OS_NAME=linux JOBS=$(nproc) ;; @@ -329,11 +312,6 @@ export SKIP_DASHED_BUILT_INS=YesPlease case "$distro" in ubuntu-*) - if test "$jobname" = "linux-gcc-default" - then - break - fi - # Python 2 is end of life, and Ubuntu 23.04 and newer don't actually # have it anymore. We thus only test with Python 2 on older LTS # releases. @@ -345,14 +323,7 @@ ubuntu-*) fi MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/$PYTHON_PACKAGE" - case "$distro" in - ubuntu-16.04) - # Apache is too old for HTTP/2. - ;; - *) - export GIT_TEST_HTTPD=true - ;; - esac + export GIT_TEST_HTTPD=true # The Linux build installs the defined dependency versions below. # The OS X build installs much more recent versions, whichever @@ -377,11 +348,11 @@ case "$jobname" in linux32) CC=gcc ;; -linux-musl) - CC=gcc - MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/python3 USE_LIBPCRE2=Yes" - MAKEFLAGS="$MAKEFLAGS NO_REGEX=Yes ICONV_OMITS_BOM=Yes" - MAKEFLAGS="$MAKEFLAGS GIT_TEST_UTF8_LOCALE=C.UTF-8" +linux-meson) + MESONFLAGS="$MESONFLAGS -Dcredential_helpers=libsecret,netrc" + ;; +linux-musl-meson) + MESONFLAGS="$MESONFLAGS -Dtest_utf8_locale=C.UTF-8" ;; linux-leaks|linux-reftable-leaks) export SANITIZE=leak @@ -391,6 +362,9 @@ linux-asan-ubsan) export NO_SVN_TESTS=LetsSaveSomeTime MAKEFLAGS="$MAKEFLAGS NO_PYTHON=YepBecauseP4FlakesTooOften" ;; +osx-meson) + MESONFLAGS="$MESONFLAGS -Dcredential_helpers=osxkeychain" + ;; esac MAKEFLAGS="$MAKEFLAGS CC=${CC:-cc}" diff --git a/ci/print-test-failures.sh b/ci/print-test-failures.sh index 655687dd82..dc910e5160 100755 --- a/ci/print-test-failures.sh +++ b/ci/print-test-failures.sh @@ -39,11 +39,6 @@ do test_name="${test_name##*/}" trash_dir="trash directory.$test_name" case "$CI_TYPE" in - azure-pipelines) - mkdir -p failed-test-artifacts - mv "$trash_dir" failed-test-artifacts - continue - ;; github-actions) mkdir -p failed-test-artifacts echo "FAILED_TEST_ARTIFACTS=${TEST_OUTPUT_DIRECTORY:t}/failed-test-artifacts" >>$GITHUB_ENV diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh index 76667a1277..1c69846723 100755 --- a/ci/run-build-and-tests.sh +++ b/ci/run-build-and-tests.sh @@ -13,8 +13,9 @@ esac run_tests=t case "$jobname" in -linux-gcc) +linux-breaking-changes) export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main + export WITH_BREAKING_CHANGES=YesPlease ;; linux-TEST-vars) export OPENSSL_SHA1_UNSAFE=YesPlease @@ -52,8 +53,11 @@ esac case "$jobname" in *-meson) group "Configure" meson setup build . \ + --fatal-meson-warnings \ --warnlevel 2 --werror \ - --wrap-mode nofallback + --wrap-mode nofallback \ + -Dfuzzers=true \ + $MESONFLAGS group "Build" meson compile -C build -- if test -n "$run_tests" then diff --git a/combine-diff.c b/combine-diff.c index 641bc92dbd..9527f3160d 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -47,31 +47,20 @@ static struct combine_diff_path *intersect_paths( if (!n) { for (i = 0; i < q->nr; i++) { - int len; - const char *path; if (diff_unmodified_pair(q->queue[i])) continue; - path = q->queue[i]->two->path; - len = strlen(path); - p = xmalloc(combine_diff_path_size(num_parent, len)); - p->path = (char *) &(p->parent[num_parent]); - memcpy(p->path, path, len); - p->path[len] = 0; - p->next = NULL; - memset(p->parent, 0, - sizeof(p->parent[0]) * num_parent); - - oidcpy(&p->oid, &q->queue[i]->two->oid); - p->mode = q->queue[i]->two->mode; + p = combine_diff_path_new(q->queue[i]->two->path, + strlen(q->queue[i]->two->path), + q->queue[i]->two->mode, + &q->queue[i]->two->oid, + num_parent); oidcpy(&p->parent[n].oid, &q->queue[i]->one->oid); p->parent[n].mode = q->queue[i]->one->mode; p->parent[n].status = q->queue[i]->status; if (combined_all_paths && filename_changed(p->parent[n].status)) { - strbuf_init(&p->parent[n].path, 0); - strbuf_addstr(&p->parent[n].path, - q->queue[i]->one->path); + p->parent[n].path = xstrdup(q->queue[i]->one->path); } *tail = p; tail = &p->next; @@ -92,9 +81,7 @@ static struct combine_diff_path *intersect_paths( /* p->path not in q->queue[]; drop it */ *tail = p->next; for (j = 0; j < num_parent; j++) - if (combined_all_paths && - filename_changed(p->parent[j].status)) - strbuf_release(&p->parent[j].path); + free(p->parent[j].path); free(p); continue; } @@ -110,8 +97,7 @@ static struct combine_diff_path *intersect_paths( p->parent[n].status = q->queue[i]->status; if (combined_all_paths && filename_changed(p->parent[n].status)) - strbuf_addstr(&p->parent[n].path, - q->queue[i]->one->path); + p->parent[n].path = xstrdup(q->queue[i]->one->path); tail = &p->next; i++; @@ -996,8 +982,9 @@ static void show_combined_header(struct combine_diff_path *elem, if (rev->combined_all_paths) { for (i = 0; i < num_parent; i++) { - char *path = filename_changed(elem->parent[i].status) - ? elem->parent[i].path.buf : elem->path; + const char *path = elem->parent[i].path ? + elem->parent[i].path : + elem->path; if (elem->parent[i].status == DIFF_STATUS_ADDED) dump_quoted_path("--- ", "", "/dev/null", line_prefix, c_meta, c_reset); @@ -1278,12 +1265,10 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re for (i = 0; i < num_parent; i++) if (rev->combined_all_paths) { - if (filename_changed(p->parent[i].status)) - write_name_quoted(p->parent[i].path.buf, stdout, - inter_name_termination); - else - write_name_quoted(p->path, stdout, - inter_name_termination); + const char *path = p->parent[i].path ? + p->parent[i].path : + p->path; + write_name_quoted(path, stdout, inter_name_termination); } write_name_quoted(p->path, stdout, line_termination); } @@ -1443,22 +1428,19 @@ static struct combine_diff_path *find_paths_multitree( { int i, nparent = parents->nr; const struct object_id **parents_oid; - struct combine_diff_path paths_head; + struct combine_diff_path *paths; struct strbuf base; ALLOC_ARRAY(parents_oid, nparent); for (i = 0; i < nparent; i++) parents_oid[i] = &parents->oid[i]; - /* fake list head, so worker can assume it is non-NULL */ - paths_head.next = NULL; - strbuf_init(&base, PATH_MAX); - diff_tree_paths(&paths_head, oid, parents_oid, nparent, &base, opt); + paths = diff_tree_paths(oid, parents_oid, nparent, &base, opt); strbuf_release(&base); free(parents_oid); - return paths_head.next; + return paths; } static int match_objfind(struct combine_diff_path *path, @@ -1645,9 +1627,7 @@ void diff_tree_combined(const struct object_id *oid, struct combine_diff_path *tmp = paths; paths = paths->next; for (i = 0; i < num_parent; i++) - if (rev->combined_all_paths && - filename_changed(tmp->parent[i].status)) - strbuf_release(&tmp->parent[i].path); + free(tmp->parent[i].path); free(tmp); } @@ -1667,3 +1647,25 @@ void diff_tree_combined_merge(const struct commit *commit, diff_tree_combined(&commit->object.oid, &parents, rev); oid_array_clear(&parents); } + +struct combine_diff_path *combine_diff_path_new(const char *path, + size_t path_len, + unsigned int mode, + const struct object_id *oid, + size_t num_parents) +{ + struct combine_diff_path *p; + size_t parent_len = st_mult(sizeof(p->parent[0]), num_parents); + + p = xmalloc(st_add4(sizeof(*p), path_len, 1, parent_len)); + p->path = (char *)&(p->parent[num_parents]); + memcpy(p->path, path, path_len); + p->path[path_len] = 0; + p->next = NULL; + p->mode = mode; + oidcpy(&p->oid, oid); + + memset(p->parent, 0, parent_len); + + return p; +} diff --git a/command-list.txt b/command-list.txt index e0bb87b3b5..b7ade3ab9f 100644 --- a/command-list.txt +++ b/command-list.txt @@ -60,6 +60,7 @@ git-annotate ancillaryinterrogators git-apply plumbingmanipulators complete git-archimport foreignscminterface git-archive mainporcelain +git-backfill mainporcelain history git-bisect mainporcelain info git-blame ancillaryinterrogators complete git-branch mainporcelain history @@ -95,6 +96,7 @@ git-diagnose ancillaryinterrogators git-diff mainporcelain info git-diff-files plumbinginterrogators git-diff-index plumbinginterrogators +git-diff-pairs plumbinginterrogators git-diff-tree plumbinginterrogators git-difftool ancillaryinterrogators complete git-fast-export ancillarymanipulators diff --git a/commit-graph.c b/commit-graph.c index 0df66e5a24..1021ccb983 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -1534,6 +1534,7 @@ static void close_reachable(struct write_commit_graph_context *ctx) if (ctx->report_progress) ctx->progress = start_delayed_progress( + the_repository, _("Loading known commits in commit graph"), ctx->oids.nr); for (i = 0; i < ctx->oids.nr; i++) { @@ -1551,6 +1552,7 @@ static void close_reachable(struct write_commit_graph_context *ctx) */ if (ctx->report_progress) ctx->progress = start_delayed_progress( + the_repository, _("Expanding reachable commits in commit graph"), 0); for (i = 0; i < ctx->oids.nr; i++) { @@ -1571,6 +1573,7 @@ static void close_reachable(struct write_commit_graph_context *ctx) if (ctx->report_progress) ctx->progress = start_delayed_progress( + the_repository, _("Clearing commit marks in commit graph"), ctx->oids.nr); for (i = 0; i < ctx->oids.nr; i++) { @@ -1688,6 +1691,7 @@ static void compute_topological_levels(struct write_commit_graph_context *ctx) if (ctx->report_progress) info.progress = ctx->progress = start_delayed_progress( + the_repository, _("Computing commit graph topological levels"), ctx->commits.nr); @@ -1722,6 +1726,7 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx) if (ctx->report_progress) info.progress = ctx->progress = start_delayed_progress( + the_repository, _("Computing commit graph generation numbers"), ctx->commits.nr); @@ -1798,6 +1803,7 @@ static void compute_bloom_filters(struct write_commit_graph_context *ctx) if (ctx->report_progress) progress = start_delayed_progress( + the_repository, _("Computing commit changed paths Bloom filters"), ctx->commits.nr); @@ -1877,6 +1883,7 @@ int write_commit_graph_reachable(struct object_directory *odb, data.commits = &commits; if (flags & COMMIT_GRAPH_WRITE_PROGRESS) data.progress = start_delayed_progress( + the_repository, _("Collecting referenced commits"), 0); refs_for_each_ref(get_main_ref_store(the_repository), add_ref_to_set, @@ -1908,7 +1915,8 @@ static int fill_oids_from_packs(struct write_commit_graph_context *ctx, "Finding commits for commit graph in %"PRIuMAX" packs", pack_indexes->nr), (uintmax_t)pack_indexes->nr); - ctx->progress = start_delayed_progress(progress_title.buf, 0); + ctx->progress = start_delayed_progress(the_repository, + progress_title.buf, 0); ctx->progress_done = 0; } for (i = 0; i < pack_indexes->nr; i++) { @@ -1959,6 +1967,7 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx) { if (ctx->report_progress) ctx->progress = start_delayed_progress( + the_repository, _("Finding commits for commit graph among packed objects"), ctx->approx_nr_objects); for_each_packed_object(ctx->r, add_packed_commits, ctx, @@ -1977,6 +1986,7 @@ static void copy_oids_to_commits(struct write_commit_graph_context *ctx) ctx->num_extra_edges = 0; if (ctx->report_progress) ctx->progress = start_delayed_progress( + the_repository, _("Finding extra edges in commit graph"), ctx->oids.nr); oid_array_sort(&ctx->oids); @@ -2074,7 +2084,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) return -1; } - if (adjust_shared_perm(get_tempfile_path(graph_layer))) { + if (adjust_shared_perm(the_repository, get_tempfile_path(graph_layer))) { error(_("unable to adjust shared permissions for '%s'"), get_tempfile_path(graph_layer)); return -1; @@ -2136,6 +2146,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) get_num_chunks(cf)), get_num_chunks(cf)); ctx->progress = start_delayed_progress( + the_repository, progress_title.buf, st_mult(get_num_chunks(cf), ctx->commits.nr)); } @@ -2348,6 +2359,7 @@ static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx) if (ctx->report_progress) ctx->progress = start_delayed_progress( + the_repository, _("Scanning merged commits"), ctx->commits.nr); @@ -2392,7 +2404,8 @@ static void merge_commit_graphs(struct write_commit_graph_context *ctx) current_graph_number--; if (ctx->report_progress) - ctx->progress = start_delayed_progress(_("Merging commit-graph"), 0); + ctx->progress = start_delayed_progress(the_repository, + _("Merging commit-graph"), 0); merge_commit_graph(ctx, g); stop_progress(&ctx->progress); @@ -2874,7 +2887,8 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags) if (!(flags & COMMIT_GRAPH_VERIFY_SHALLOW)) total += g->num_commits_in_base; - progress = start_progress(_("Verifying commits in commit graph"), + progress = start_progress(the_repository, + _("Verifying commits in commit graph"), total); } diff --git a/commit-reach.c b/commit-reach.c index e3edd11995..a339e41aa4 100644 --- a/commit-reach.c +++ b/commit-reach.c @@ -1,5 +1,4 @@ #define USE_THE_REPOSITORY_VARIABLE -#define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" #include "commit.h" @@ -42,8 +41,7 @@ static int compare_commits_by_gen(const void *_a, const void *_b) static int queue_has_nonstale(struct prio_queue *queue) { - int i; - for (i = 0; i < queue->nr; i++) { + for (size_t i = 0; i < queue->nr; i++) { struct commit *commit = queue->array[i].data; if (!(commit->object.flags & STALE)) return 1; @@ -213,12 +211,13 @@ int get_octopus_merge_bases(struct commit_list *in, struct commit_list **result) } static int remove_redundant_no_gen(struct repository *r, - struct commit **array, int cnt) + struct commit **array, + size_t cnt, size_t *dedup_cnt) { struct commit **work; unsigned char *redundant; - int *filled_index; - int i, j, filled; + size_t *filled_index; + size_t i, j, filled; CALLOC_ARRAY(work, cnt); redundant = xcalloc(cnt, 1); @@ -268,20 +267,22 @@ static int remove_redundant_no_gen(struct repository *r, for (i = filled = 0; i < cnt; i++) if (!redundant[i]) array[filled++] = work[i]; + *dedup_cnt = filled; free(work); free(redundant); free(filled_index); - return filled; + return 0; } static int remove_redundant_with_gen(struct repository *r, - struct commit **array, int cnt) + struct commit **array, size_t cnt, + size_t *dedup_cnt) { - int i, count_non_stale = 0, count_still_independent = cnt; + size_t i, count_non_stale = 0, count_still_independent = cnt; timestamp_t min_generation = GENERATION_NUMBER_INFINITY; struct commit **walk_start, **sorted; size_t walk_start_nr = 0, walk_start_alloc = cnt; - int min_gen_pos = 0; + size_t min_gen_pos = 0; /* * Sort the input by generation number, ascending. This allows @@ -327,12 +328,12 @@ static int remove_redundant_with_gen(struct repository *r, * terminate early. Otherwise, we will do the same amount of work * as before. */ - for (i = walk_start_nr - 1; i >= 0 && count_still_independent > 1; i--) { + for (i = walk_start_nr; i && count_still_independent > 1; i--) { /* push the STALE bits up to min generation */ struct commit_list *stack = NULL; - commit_list_insert(walk_start[i], &stack); - walk_start[i]->object.flags |= STALE; + commit_list_insert(walk_start[i - 1], &stack); + walk_start[i - 1]->object.flags |= STALE; while (stack) { struct commit_list *parents; @@ -389,10 +390,12 @@ static int remove_redundant_with_gen(struct repository *r, clear_commit_marks_many(walk_start_nr, walk_start, STALE); free(walk_start); - return count_non_stale; + *dedup_cnt = count_non_stale; + return 0; } -static int remove_redundant(struct repository *r, struct commit **array, int cnt) +static int remove_redundant(struct repository *r, struct commit **array, + size_t cnt, size_t *dedup_cnt) { /* * Some commit in the array may be an ancestor of @@ -402,31 +405,30 @@ static int remove_redundant(struct repository *r, struct commit **array, int cnt * that number. */ if (generation_numbers_enabled(r)) { - int i; - /* * If we have a single commit with finite generation * number, then the _with_gen algorithm is preferred. */ - for (i = 0; i < cnt; i++) { + for (size_t i = 0; i < cnt; i++) { if (commit_graph_generation(array[i]) < GENERATION_NUMBER_INFINITY) - return remove_redundant_with_gen(r, array, cnt); + return remove_redundant_with_gen(r, array, cnt, dedup_cnt); } } - return remove_redundant_no_gen(r, array, cnt); + return remove_redundant_no_gen(r, array, cnt, dedup_cnt); } static int get_merge_bases_many_0(struct repository *r, struct commit *one, - int n, + size_t n, struct commit **twos, int cleanup, struct commit_list **result) { struct commit_list *list; struct commit **rslt; - int cnt, i; + size_t cnt, i; + int ret; if (merge_bases_many(r, one, n, twos, result) < 0) return -1; @@ -453,8 +455,8 @@ static int get_merge_bases_many_0(struct repository *r, clear_commit_marks(one, all_flags); clear_commit_marks_many(n, twos, all_flags); - cnt = remove_redundant(r, rslt, cnt); - if (cnt < 0) { + ret = remove_redundant(r, rslt, cnt, &cnt); + if (ret < 0) { free(rslt); return -1; } @@ -466,7 +468,7 @@ static int get_merge_bases_many_0(struct repository *r, int repo_get_merge_bases_many(struct repository *r, struct commit *one, - int n, + size_t n, struct commit **twos, struct commit_list **result) { @@ -475,7 +477,7 @@ int repo_get_merge_bases_many(struct repository *r, int repo_get_merge_bases_many_dirty(struct repository *r, struct commit *one, - int n, + size_t n, struct commit **twos, struct commit_list **result) { @@ -583,7 +585,8 @@ struct commit_list *reduce_heads(struct commit_list *heads) struct commit_list *p; struct commit_list *result = NULL, **tail = &result; struct commit **array; - int num_head, i; + size_t num_head, i; + int ret; if (!heads) return NULL; @@ -604,11 +607,13 @@ struct commit_list *reduce_heads(struct commit_list *heads) p->item->object.flags &= ~STALE; } } - num_head = remove_redundant(the_repository, array, num_head); - if (num_head < 0) { + + ret = remove_redundant(the_repository, array, num_head, &num_head); + if (ret < 0) { free(array); return NULL; } + for (i = 0; i < num_head; i++) tail = &commit_list_insert(array[i], tail)->next; free(array); @@ -781,12 +786,12 @@ int commit_contains(struct ref_filter *filter, struct commit *commit, int can_all_from_reach_with_flag(struct object_array *from, unsigned int with_flag, unsigned int assign_flag, - time_t min_commit_date, + timestamp_t min_commit_date, timestamp_t min_generation) { struct commit **list = NULL; - int i; - int nr_commits; + size_t i; + size_t nr_commits; int result = 1; ALLOC_ARRAY(list, from->nr); @@ -884,9 +889,9 @@ int can_all_from_reach(struct commit_list *from, struct commit_list *to, int cutoff_by_min_date) { struct object_array from_objs = OBJECT_ARRAY_INIT; - time_t min_commit_date = cutoff_by_min_date ? from->item->date : 0; struct commit_list *from_iter = from, *to_iter = to; int result; + timestamp_t min_commit_date = cutoff_by_min_date ? from->item->date : 0; timestamp_t min_generation = GENERATION_NUMBER_INFINITY; while (from_iter) { @@ -938,8 +943,8 @@ int can_all_from_reach(struct commit_list *from, struct commit_list *to, return result; } -struct commit_list *get_reachable_subset(struct commit **from, int nr_from, - struct commit **to, int nr_to, +struct commit_list *get_reachable_subset(struct commit **from, size_t nr_from, + struct commit **to, size_t nr_to, unsigned int reachable_flag) { struct commit **item; diff --git a/commit-reach.h b/commit-reach.h index 9a745b7e17..6012402dfc 100644 --- a/commit-reach.h +++ b/commit-reach.h @@ -14,12 +14,12 @@ int repo_get_merge_bases(struct repository *r, struct commit *rev2, struct commit_list **result); int repo_get_merge_bases_many(struct repository *r, - struct commit *one, int n, + struct commit *one, size_t n, struct commit **twos, struct commit_list **result); /* To be used only when object flags after this call no longer matter */ int repo_get_merge_bases_many_dirty(struct repository *r, - struct commit *one, int n, + struct commit *one, size_t n, struct commit **twos, struct commit_list **result); @@ -81,7 +81,7 @@ int commit_contains(struct ref_filter *filter, struct commit *commit, int can_all_from_reach_with_flag(struct object_array *from, unsigned int with_flag, unsigned int assign_flag, - time_t min_commit_date, + timestamp_t min_commit_date, timestamp_t min_generation); int can_all_from_reach(struct commit_list *from, struct commit_list *to, int commit_date_cutoff); @@ -95,8 +95,8 @@ int can_all_from_reach(struct commit_list *from, struct commit_list *to, * This method uses the PARENT1 and PARENT2 flags during its operation, * so be sure these flags are not set before calling the method. */ -struct commit_list *get_reachable_subset(struct commit **from, int nr_from, - struct commit **to, int nr_to, +struct commit_list *get_reachable_subset(struct commit **from, size_t nr_from, + struct commit **to, size_t nr_to, unsigned int reachable_flag); struct ahead_behind_count { @@ -778,16 +778,16 @@ static void clear_commit_marks_1(struct commit_list **plist, } } -void clear_commit_marks_many(int nr, struct commit **commit, unsigned int mark) +void clear_commit_marks_many(size_t nr, struct commit **commit, unsigned int mark) { - struct commit_list *list = NULL; + for (size_t i = 0; i < nr; i++) { + struct commit_list *list = NULL; - while (nr--) { clear_commit_marks_1(&list, *commit, mark); + while (list) + clear_commit_marks_1(&list, pop_commit(&list), mark); commit++; } - while (list) - clear_commit_marks_1(&list, pop_commit(&list), mark); } void clear_commit_marks(struct commit *commit, unsigned int mark) @@ -210,7 +210,7 @@ struct commit *pop_most_recent_commit(struct commit_list **list, struct commit *pop_commit(struct commit_list **stack); void clear_commit_marks(struct commit *commit, unsigned int mark); -void clear_commit_marks_many(int nr, struct commit **commit, unsigned int mark); +void clear_commit_marks_many(size_t nr, struct commit **commit, unsigned int mark); enum rev_sort_order { diff --git a/common-exit.c b/common-exit.c new file mode 100644 index 0000000000..1aaa538be3 --- /dev/null +++ b/common-exit.c @@ -0,0 +1,26 @@ +#include "git-compat-util.h" +#include "trace2.h" + +static void check_bug_if_BUG(void) +{ + if (!bug_called_must_BUG) + return; + BUG("on exit(): had bug() call(s) in this process without explicit BUG_if_bug()"); +} + +/* We wrap exit() to call common_exit() in git-compat-util.h */ +int common_exit(const char *file, int line, int code) +{ + /* + * For non-POSIX systems: Take the lowest 8 bits of the "code" + * to e.g. turn -1 into 255. On a POSIX system this is + * redundant, see exit(3) and wait(2), but as it doesn't harm + * anything there we don't need to guard this with an "ifdef". + */ + code &= 0xff; + + check_bug_if_BUG(); + trace2_cmd_exit_fl(file, line, code); + + return code; +} diff --git a/common-init.c b/common-init.c new file mode 100644 index 0000000000..5cc73f058c --- /dev/null +++ b/common-init.c @@ -0,0 +1,63 @@ +#define USE_THE_REPOSITORY_VARIABLE + +#include "git-compat-util.h" +#include "common-init.h" +#include "exec-cmd.h" +#include "gettext.h" +#include "attr.h" +#include "repository.h" +#include "setup.h" +#include "strbuf.h" +#include "trace2.h" + +/* + * Many parts of Git have subprograms communicate via pipe, expect the + * upstream of a pipe to die with SIGPIPE when the downstream of a + * pipe does not need to read all that is written. Some third-party + * programs that ignore or block SIGPIPE for their own reason forget + * to restore SIGPIPE handling to the default before spawning Git and + * break this carefully orchestrated machinery. + * + * Restore the way SIGPIPE is handled to default, which is what we + * expect. + */ +static void restore_sigpipe_to_default(void) +{ + sigset_t unblock; + + sigemptyset(&unblock); + sigaddset(&unblock, SIGPIPE); + sigprocmask(SIG_UNBLOCK, &unblock, NULL); + signal(SIGPIPE, SIG_DFL); +} + +void init_git(const char **argv) +{ + struct strbuf tmp = STRBUF_INIT; + + trace2_initialize_clock(); + + /* + * Always open file descriptors 0/1/2 to avoid clobbering files + * in die(). It also avoids messing up when the pipes are dup'ed + * onto stdin/stdout/stderr in the child processes we spawn. + */ + sanitize_stdfds(); + restore_sigpipe_to_default(); + + git_resolve_executable_dir(argv[0]); + + setlocale(LC_CTYPE, ""); + git_setup_gettext(); + + initialize_repository(the_repository); + + attr_start(); + + trace2_initialize(); + trace2_cmd_start(argv); + trace2_collect_process_info(TRACE2_PROCESS_INFO_STARTUP); + + if (!strbuf_getcwd(&tmp)) + tmp_original_cwd = strbuf_detach(&tmp, NULL); +} diff --git a/common-init.h b/common-init.h new file mode 100644 index 0000000000..3e6db20cae --- /dev/null +++ b/common-init.h @@ -0,0 +1,6 @@ +#ifndef COMMON_INIT_H +#define COMMON_INIT_H + +void init_git(const char **argv); + +#endif /* COMMON_INIT_H */ diff --git a/common-main.c b/common-main.c index 8e68ac9e42..6b7ab077b0 100644 --- a/common-main.c +++ b/common-main.c @@ -1,92 +1,13 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" -#include "exec-cmd.h" -#include "gettext.h" -#include "attr.h" -#include "repository.h" -#include "setup.h" -#include "strbuf.h" -#include "trace2.h" - -/* - * Many parts of Git have subprograms communicate via pipe, expect the - * upstream of a pipe to die with SIGPIPE when the downstream of a - * pipe does not need to read all that is written. Some third-party - * programs that ignore or block SIGPIPE for their own reason forget - * to restore SIGPIPE handling to the default before spawning Git and - * break this carefully orchestrated machinery. - * - * Restore the way SIGPIPE is handled to default, which is what we - * expect. - */ -static void restore_sigpipe_to_default(void) -{ - sigset_t unblock; - - sigemptyset(&unblock); - sigaddset(&unblock, SIGPIPE); - sigprocmask(SIG_UNBLOCK, &unblock, NULL); - signal(SIGPIPE, SIG_DFL); -} +#include "common-init.h" int main(int argc, const char **argv) { int result; - struct strbuf tmp = STRBUF_INIT; - - trace2_initialize_clock(); - - /* - * Always open file descriptors 0/1/2 to avoid clobbering files - * in die(). It also avoids messing up when the pipes are dup'ed - * onto stdin/stdout/stderr in the child processes we spawn. - */ - sanitize_stdfds(); - restore_sigpipe_to_default(); - - git_resolve_executable_dir(argv[0]); - - setlocale(LC_CTYPE, ""); - git_setup_gettext(); - - initialize_repository(the_repository); - - attr_start(); - - trace2_initialize(); - trace2_cmd_start(argv); - trace2_collect_process_info(TRACE2_PROCESS_INFO_STARTUP); - - if (!strbuf_getcwd(&tmp)) - tmp_original_cwd = strbuf_detach(&tmp, NULL); + init_git(argv); result = cmd_main(argc, argv); /* Not exit(3), but a wrapper calling our common_exit() */ exit(result); } - -static void check_bug_if_BUG(void) -{ - if (!bug_called_must_BUG) - return; - BUG("on exit(): had bug() call(s) in this process without explicit BUG_if_bug()"); -} - -/* We wrap exit() to call common_exit() in git-compat-util.h */ -int common_exit(const char *file, int line, int code) -{ - /* - * For non-POSIX systems: Take the lowest 8 bits of the "code" - * to e.g. turn -1 into 255. On a POSIX system this is - * redundant, see exit(3) and wait(2), but as it doesn't harm - * anything there we don't need to guard this with an "ifdef". - */ - code &= 0xff; - - check_bug_if_BUG(); - trace2_cmd_exit_fl(file, line, code); - - return code; -} diff --git a/compat/bswap.h b/compat/bswap.h index 512f6f4b99..b34054f2bd 100644 --- a/compat/bswap.h +++ b/compat/bswap.h @@ -171,23 +171,23 @@ static inline uint64_t get_be64(const void *ptr) static inline void put_be32(void *ptr, uint32_t value) { unsigned char *p = ptr; - p[0] = value >> 24; - p[1] = value >> 16; - p[2] = value >> 8; - p[3] = value >> 0; + p[0] = (value >> 24) & 0xff; + p[1] = (value >> 16) & 0xff; + p[2] = (value >> 8) & 0xff; + p[3] = (value >> 0) & 0xff; } static inline void put_be64(void *ptr, uint64_t value) { unsigned char *p = ptr; - p[0] = value >> 56; - p[1] = value >> 48; - p[2] = value >> 40; - p[3] = value >> 32; - p[4] = value >> 24; - p[5] = value >> 16; - p[6] = value >> 8; - p[7] = value >> 0; + p[0] = (value >> 56) & 0xff; + p[1] = (value >> 48) & 0xff; + p[2] = (value >> 40) & 0xff; + p[3] = (value >> 32) & 0xff; + p[4] = (value >> 24) & 0xff; + p[5] = (value >> 16) & 0xff; + p[6] = (value >> 8) & 0xff; + p[7] = (value >> 0) & 0xff; } #endif /* COMPAT_BSWAP_H */ diff --git a/compat/mingw.c b/compat/mingw.c index 1d5b211b54..f524c54d06 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2278,7 +2278,9 @@ repeat: old_handle = CreateFileW(wpold, DELETE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, + NULL); if (old_handle == INVALID_HANDLE_VALUE) { errno = err_win_to_posix(GetLastError()); return -1; diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c index f7cc7b3be5..12e38e0ea3 100644 --- a/compat/precompose_utf8.c +++ b/compat/precompose_utf8.c @@ -50,15 +50,15 @@ void probe_utf8_pathname_composition(void) int output_fd; if (precomposed_unicode != -1) return; /* We found it defined in the global config, respect it */ - git_path_buf(&path, "%s", auml_nfc); + repo_git_path_replace(the_repository, &path, "%s", auml_nfc); output_fd = open(path.buf, O_CREAT|O_EXCL|O_RDWR, 0600); if (output_fd >= 0) { close(output_fd); - git_path_buf(&path, "%s", auml_nfd); + repo_git_path_replace(the_repository, &path, "%s", auml_nfd); precomposed_unicode = access(path.buf, R_OK) ? 0 : 1; git_config_set("core.precomposeunicode", precomposed_unicode ? "true" : "false"); - git_path_buf(&path, "%s", auml_nfc); + repo_git_path_replace(the_repository, &path, "%s", auml_nfc); if (unlink(path.buf)) die_errno(_("failed to unlink '%s'"), path.buf); } diff --git a/compat/zlib-compat.h b/compat/zlib-compat.h new file mode 100644 index 0000000000..0c60e3af33 --- /dev/null +++ b/compat/zlib-compat.h @@ -0,0 +1,53 @@ +#ifndef COMPAT_ZLIB_H +#define COMPAT_ZLIB_H + +#ifdef HAVE_ZLIB_NG +# include <zlib-ng.h> + +# define z_stream zng_stream +#define gz_header_s zng_gz_header_s + +# define crc32(crc, buf, len) zng_crc32(crc, buf, len) + +# define inflate(strm, bits) zng_inflate(strm, bits) +# define inflateEnd(strm) zng_inflateEnd(strm) +# define inflateInit(strm) zng_inflateInit(strm) +# define inflateInit2(strm, bits) zng_inflateInit2(strm, bits) +# define inflateReset(strm) zng_inflateReset(strm) + +# define deflate(strm, flush) zng_deflate(strm, flush) +# define deflateBound(strm, source_len) zng_deflateBound(strm, source_len) +# define deflateEnd(strm) zng_deflateEnd(strm) +# define deflateInit(strm, level) zng_deflateInit(strm, level) +# define deflateInit2(stream, level, method, window_bits, mem_level, strategy) zng_deflateInit2(stream, level, method, window_bits, mem_level, strategy) +# define deflateReset(strm) zng_deflateReset(strm) +# define deflateSetHeader(strm, head) zng_deflateSetHeader(strm, head) + +#else +# include <zlib.h> + +# if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200 +# define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11) +# endif + +/* + * zlib only gained support for setting up the gzip header in v1.2.2.1. In + * Git we only set the header to make archives reproducible across different + * operating systems, so it's fine to simply make this a no-op when using a + * zlib version that doesn't support this yet. + */ +# if ZLIB_VERNUM < 0x1221 +struct gz_header_s { + int os; +}; + +static int deflateSetHeader(z_streamp strm, struct gz_header_s *head) +{ + (void)(strm); + (void)(head); + return Z_OK; +} +# endif +#endif /* HAVE_ZLIB_NG */ + +#endif /* COMPAT_ZLIB_H */ diff --git a/compat/zlib-uncompress2.c b/compat/zlib-uncompress2.c deleted file mode 100644 index 77a1b08048..0000000000 --- a/compat/zlib-uncompress2.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "git-compat-util.h" - -#if ZLIB_VERNUM < 0x1290 -/* taken from zlib's uncompr.c - - commit cacf7f1d4e3d44d871b605da3b647f07d718623f - Author: Mark Adler <madler@alumni.caltech.edu> - Date: Sun Jan 15 09:18:46 2017 -0800 - - zlib 1.2.11 - -*/ - -/* - * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* clang-format off */ - -/* =========================================================================== - Decompresses the source buffer into the destination buffer. *sourceLen is - the byte length of the source buffer. Upon entry, *destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, - *destLen is the size of the decompressed data and *sourceLen is the number - of source bytes consumed. Upon return, source + *sourceLen points to the - first unused input byte. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, or - Z_DATA_ERROR if the input data was corrupted, including if the input data is - an incomplete zlib stream. -*/ -int ZEXPORT uncompress2 ( - Bytef *dest, - uLongf *destLen, - const Bytef *source, - uLong *sourceLen) { - z_stream stream; - int err; - const uInt max = (uInt)-1; - uLong len, left; - Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */ - - len = *sourceLen; - if (*destLen) { - left = *destLen; - *destLen = 0; - } - else { - left = 1; - dest = buf; - } - - stream.next_in = (z_const Bytef *)source; - stream.avail_in = 0; - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; - - err = inflateInit(&stream); - if (err != Z_OK) return err; - - stream.next_out = dest; - stream.avail_out = 0; - - do { - if (stream.avail_out == 0) { - stream.avail_out = left > (uLong)max ? max : (uInt)left; - left -= stream.avail_out; - } - if (stream.avail_in == 0) { - stream.avail_in = len > (uLong)max ? max : (uInt)len; - len -= stream.avail_in; - } - err = inflate(&stream, Z_NO_FLUSH); - } while (err == Z_OK); - - *sourceLen -= len + stream.avail_in; - if (dest != buf) - *destLen = stream.total_out; - else if (stream.total_out && err == Z_BUF_ERROR) - left = 1; - - inflateEnd(&stream); - return err == Z_STREAM_END ? Z_OK : - err == Z_NEED_DICT ? Z_DATA_ERROR : - err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR : - err; -} -#else -static void *dummy_variable = &dummy_variable; -#endif @@ -19,6 +19,7 @@ #include "convert.h" #include "environment.h" #include "gettext.h" +#include "git-zlib.h" #include "ident.h" #include "repository.h" #include "lockfile.h" @@ -1436,11 +1437,6 @@ static int git_default_core_config(const char *var, const char *value, return git_config_pathname(&git_attributes_file, var, value); } - if (!strcmp(var, "core.hookspath")) { - FREE_AND_NULL(git_hooks_path); - return git_config_pathname(&git_hooks_path, var, value); - } - if (!strcmp(var, "core.bare")) { is_bare_repository_cfg = git_config_bool(var, value); return 0; @@ -1651,7 +1647,7 @@ static int git_default_core_config(const char *var, const char *value, return 0; } - /* Add other config variables here and to Documentation/config.txt. */ + /* Add other config variables here and to Documentation/config.adoc. */ return platform_core_config(var, value, ctx, cb); } @@ -1662,7 +1658,7 @@ static int git_default_sparse_config(const char *var, const char *value) return 0; } - /* Add other config variables here and to Documentation/config/sparse.txt. */ + /* Add other config variables here and to Documentation/config/sparse.adoc. */ return 0; } @@ -1678,7 +1674,7 @@ static int git_default_i18n_config(const char *var, const char *value) return git_config_string(&git_log_output_encoding, var, value); } - /* Add other config variables here and to Documentation/config.txt. */ + /* Add other config variables here and to Documentation/config.adoc. */ return 0; } @@ -1714,7 +1710,7 @@ static int git_default_branch_config(const char *var, const char *value) return 0; } - /* Add other config variables here and to Documentation/config.txt. */ + /* Add other config variables here and to Documentation/config.adoc. */ return 0; } @@ -1743,7 +1739,7 @@ static int git_default_push_config(const char *var, const char *value) return 0; } - /* Add other config variables here and to Documentation/config.txt. */ + /* Add other config variables here and to Documentation/config.adoc. */ return 0; } @@ -1759,7 +1755,7 @@ static int git_default_mailmap_config(const char *var, const char *value) return git_config_string(&git_mailmap_blob, var, value); } - /* Add other config variables here and to Documentation/config.txt. */ + /* Add other config variables here and to Documentation/config.adoc. */ return 0; } @@ -1772,7 +1768,7 @@ static int git_default_attr_config(const char *var, const char *value) /* * Add other attribute related config variables here and to - * Documentation/config/attr.txt. + * Documentation/config/attr.adoc. */ return 0; } @@ -1830,7 +1826,7 @@ int git_default_config(const char *var, const char *value, if (starts_with(var, "sparse.")) return git_default_sparse_config(var, value); - /* Add other config variables here and to Documentation/config.txt. */ + /* Add other config variables here and to Documentation/config.adoc. */ return 0; } @@ -2525,6 +2521,10 @@ void repo_config_clear(struct repository *repo) void repo_config(struct repository *repo, config_fn_t fn, void *data) { + if (!repo) { + read_very_early_config(fn, data); + return; + } git_config_check_init(repo); configset_iter(repo->config, fn, data); } @@ -219,6 +219,15 @@ void read_very_early_config(config_fn_t cb, void *data); * repo-specific one; by overwriting, the higher-priority repo-specific * value is left at the end). * + * In cases where the repository variable is NULL, repo_config() will + * skip the per-repository config but retain system and global configs + * by calling read_very_early_config() which also ignores one-time + * overrides like "git -c var=val". This is to support handling "git foo -h" + * (which lets git.c:run_builtin() to pass NULL and have the cmd_foo() + * call repo_config() before calling parse_options() to notice "-h", give + * help and exit) for a command that ordinarily require a repository + * so this limitation may be OK (but if needed you are welcome to fix it). + * * Unlike git_config_from_file(), this function respects includes. */ void repo_config(struct repository *r, config_fn_t fn, void *); @@ -1,5 +1,4 @@ #define USE_THE_REPOSITORY_VARIABLE -#define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" #include "config.h" @@ -23,6 +22,7 @@ #include "protocol.h" #include "alias.h" #include "bundle-uri.h" +#include "promisor-remote.h" static char *server_capabilities_v1; static struct strvec server_capabilities_v2 = STRVEC_INIT; @@ -77,7 +77,7 @@ static NORETURN void die_initial_contact(int unexpected) /* Checks if the server supports the capability 'c' */ int server_supports_v2(const char *c) { - int i; + size_t i; for (i = 0; i < server_capabilities_v2.nr; i++) { const char *out; @@ -96,7 +96,7 @@ void ensure_server_supports_v2(const char *c) int server_feature_v2(const char *c, const char **v) { - int i; + size_t i; for (i = 0; i < server_capabilities_v2.nr; i++) { const char *out; @@ -112,7 +112,7 @@ int server_feature_v2(const char *c, const char **v) int server_supports_feature(const char *c, const char *feature, int die_on_error) { - int i; + size_t i; for (i = 0; i < server_capabilities_v2.nr; i++) { const char *out; @@ -232,12 +232,12 @@ static void annotate_refs_with_symref_info(struct ref *ref) string_list_clear(&symref, 0); } -static void process_capabilities(struct packet_reader *reader, int *linelen) +static void process_capabilities(struct packet_reader *reader, size_t *linelen) { const char *feat_val; size_t feat_len; const char *line = reader->line; - int nul_location = strlen(line); + size_t nul_location = strlen(line); if (nul_location == *linelen) return; server_capabilities_v1 = xstrdup(line + nul_location + 1); @@ -271,14 +271,14 @@ static int process_dummy_ref(const struct packet_reader *reader) !strcmp(name, "capabilities^{}"); } -static void check_no_capabilities(const char *line, int len) +static void check_no_capabilities(const char *line, size_t len) { if (strlen(line) != len) warning(_("ignoring capabilities after first line '%s'"), line + strlen(line)); } -static int process_ref(const struct packet_reader *reader, int len, +static int process_ref(const struct packet_reader *reader, size_t len, struct ref ***list, unsigned int flags, struct oid_array *extra_have) { @@ -306,7 +306,7 @@ static int process_ref(const struct packet_reader *reader, int len, return 1; } -static int process_shallow(const struct packet_reader *reader, int len, +static int process_shallow(const struct packet_reader *reader, size_t len, struct oid_array *shallow_points) { const char *line = reader->line; @@ -341,7 +341,7 @@ struct ref **get_remote_heads(struct packet_reader *reader, struct oid_array *shallow_points) { struct ref **orig_list = list; - int len = 0; + size_t len = 0; enum get_remote_heads_state state = EXPECTING_FIRST_REF; *list = NULL; @@ -394,7 +394,7 @@ static int process_ref_v2(struct packet_reader *reader, struct ref ***list, const char **unborn_head_target) { int ret = 1; - int i = 0; + size_t i = 0; struct object_id old_oid; struct ref *ref; struct string_list line_sections = STRING_LIST_INIT_DUP; @@ -488,6 +488,7 @@ void check_stateless_delimiter(int stateless_rpc, static void send_capabilities(int fd_out, struct packet_reader *reader) { const char *hash_name; + const char *promisor_remote_info; if (server_supports_v2("agent")) packet_write_fmt(fd_out, "agent=%s", git_user_agent_sanitized()); @@ -501,6 +502,13 @@ static void send_capabilities(int fd_out, struct packet_reader *reader) } else { reader->hash_algo = &hash_algos[GIT_HASH_SHA1]; } + if (server_feature_v2("promisor-remote", &promisor_remote_info)) { + char *reply = promisor_remote_reply(promisor_remote_info); + if (reply) { + packet_write_fmt(fd_out, "promisor-remote=%s", reply); + free(reply); + } + } } int get_remote_bundle_uri(int fd_out, struct packet_reader *reader, @@ -552,7 +560,7 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader, const struct string_list *server_options, int stateless_rpc) { - int i; + size_t i; struct strvec *ref_prefixes = transport_options ? &transport_options->ref_prefixes : NULL; const char **unborn_head_target = transport_options ? @@ -625,7 +633,7 @@ const char *parse_feature_value(const char *feature_list, const char *feature, s *offset = found + len - orig_start; return value; } - /* feature with a value (e.g., "agent=git/1.2.3") */ + /* feature with a value (e.g., "agent=git/1.2.3-Linux") */ else if (*value == '=') { size_t end; diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 10dc54fdcb..25b495fa73 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -1001,10 +1001,14 @@ parse_makefile_for_sources(unit-test_SOURCES ${CMAKE_SOURCE_DIR}/Makefile "UNIT_ list(TRANSFORM unit-test_SOURCES REPLACE "\\$\\(UNIT_TEST_DIR\\)/" "${CMAKE_SOURCE_DIR}/t/unit-tests/") add_library(unit-test-lib STATIC ${unit-test_SOURCES}) +parse_makefile_for_sources(clar-test_SOURCES ${CMAKE_SOURCE_DIR}/Makefile "CLAR_TEST_OBJS") +list(TRANSFORM clar-test_SOURCES REPLACE "\\$\\(UNIT_TEST_DIR\\)/" "${CMAKE_SOURCE_DIR}/t/unit-tests/") +add_library(clar-test-lib STATIC ${clar-test_SOURCES}) + parse_makefile_for_scripts(unit_test_PROGRAMS "UNIT_TEST_PROGRAMS" "") foreach(unit_test ${unit_test_PROGRAMS}) add_executable("${unit_test}" "${CMAKE_SOURCE_DIR}/t/unit-tests/${unit_test}.c") - target_link_libraries("${unit_test}" unit-test-lib common-main) + target_link_libraries("${unit_test}" unit-test-lib clar-test-lib common-main) set_target_properties("${unit_test}" PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/unit-tests/bin) if(MSVC) @@ -1046,13 +1050,13 @@ add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/t/unit-tests/clar.suite" VERBATIM) add_library(unit-tests-lib ${clar_test_SUITES} - "${CMAKE_SOURCE_DIR}/t/unit-tests/clar/clar.c" "${CMAKE_BINARY_DIR}/t/unit-tests/clar-decls.h" "${CMAKE_BINARY_DIR}/t/unit-tests/clar.suite" ) +target_include_directories(clar-test-lib PUBLIC "${CMAKE_BINARY_DIR}/t/unit-tests") target_include_directories(unit-tests-lib PUBLIC "${CMAKE_BINARY_DIR}/t/unit-tests") -add_executable(unit-tests "${CMAKE_SOURCE_DIR}/t/unit-tests/unit-test.c") -target_link_libraries(unit-tests unit-tests-lib common-main) +add_executable(unit-tests) +target_link_libraries(unit-tests unit-tests-lib clar-test-lib common-main) set_target_properties(unit-tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/unit-tests/bin) if(MSVC) @@ -1169,14 +1173,13 @@ string(REPLACE "@GIT_PERF_MAKE_COMMAND@" "" git_build_options "${git_build_optio string(REPLACE "@GIT_PERF_MAKE_OPTS@" "" git_build_options "${git_build_options}") string(REPLACE "@GIT_PERF_REPEAT_COUNT@" "" git_build_options "${git_build_options}") string(REPLACE "@GIT_PERF_REPO@" "" git_build_options "${git_build_options}") +string(REPLACE "@GIT_SOURCE_DIR@" "${CMAKE_SOURCE_DIR}" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_CMP@" "" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_CMP_USE_COPIED_CONTEXT@" "" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_GITPERLLIB@" "'${CMAKE_BINARY_DIR}/perl/build/lib'" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_INDEX_VERSION@" "" git_build_options "${git_build_options}") -string(REPLACE "@GIT_TEST_MERGE_TOOLS_DIR@" "'${CMAKE_BINARY_DIR}/mergetools'" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_OPTS@" "" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_PERL_FATAL_WARNINGS@" "" git_build_options "${git_build_options}") -string(REPLACE "@GIT_TEST_POPATH@" "'${CMAKE_BINARY_DIR}/po'" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_TEMPLATE_DIR@" "'${CMAKE_BINARY_DIR}/templates/blt'" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_TEXTDOMAINDIR@" "'${CMAKE_BINARY_DIR}/po/build/locale'" git_build_options "${git_build_options}") string(REPLACE "@GIT_TEST_UTF8_LOCALE@" "" git_build_options "${git_build_options}") @@ -1205,6 +1208,7 @@ string(REPLACE "@TEST_OUTPUT_DIRECTORY@" "" git_build_options "${git_build_optio string(REPLACE "@TEST_SHELL_PATH@" "'${TEST_SHELL_PATH}'" git_build_options "${git_build_options}") string(REPLACE "@USE_GETTEXT_SCHEME@" "" git_build_options "${git_build_options}") string(REPLACE "@USE_LIBPCRE2@" "" git_build_options "${git_build_options}") +string(REPLACE "@WITH_BREAKING_CHANGES@" "" git_build_options "${git_build_options}") string(REPLACE "@X@" "${EXE_EXTENSION}" git_build_options "${git_build_options}") if(USE_VCPKG) string(APPEND git_build_options "PATH=\"$PATH:$TEST_DIRECTORY/../compat/vcbuild/vcpkg/installed/x64-windows/bin\"\n") diff --git a/contrib/coccinelle/meson.build b/contrib/coccinelle/meson.build new file mode 100644 index 0000000000..5d76a7fee6 --- /dev/null +++ b/contrib/coccinelle/meson.build @@ -0,0 +1,89 @@ +spatch = find_program('spatch', required: get_option('coccinelle')) +if not spatch.found() + subdir_done() +endif + +third_party_sources = [ + ':!contrib', + ':!compat/inet_ntop.c', + ':!compat/inet_pton.c', + ':!compat/nedmalloc', + ':!compat/obstack.*', + ':!compat/poll', + ':!compat/regex', + ':!sha1collisiondetection', + ':!sha1dc', + ':!t/unit-tests/clar', + ':!t/unit-tests/clar', + ':!t/t[0-9][0-9][0-9][0-9]*', +] + +rules = [ + 'array.cocci', + 'commit.cocci', + 'config_fn_ctx.pending.cocci', + 'equals-null.cocci', + 'flex_alloc.cocci', + 'free.cocci', + 'git_config_number.cocci', + 'hashmap.cocci', + 'index-compatibility.cocci', + 'object_id.cocci', + 'preincr.cocci', + 'qsort.cocci', + 'refs.cocci', + 'strbuf.cocci', + 'swap.cocci', + 'the_repository.cocci', + 'xcalloc.cocci', + 'xopen.cocci', + 'xstrdup_or_null.cocci', + 'xstrncmpz.cocci', +] + +concatenated_rules = custom_target( + command: [ + 'cat', '@INPUT@', + ], + input: rules, + output: 'rules.cocci', + capture: true, +) + +sources = [ ] +foreach source : run_command(git, '-C', meson.project_source_root(), 'ls-files', '--deduplicate', '*.c', third_party_sources, check: true).stdout().split() + sources += source +endforeach + +headers = [ ] +foreach header : run_command(git, '-C', meson.project_source_root(), 'ls-files', '--deduplicate', '*.h', third_party_sources, check: true).stdout().split() + headers += meson.project_source_root() / header +endforeach + +patches = [ ] +foreach source : sources + patches += custom_target( + command: [ + spatch, + '--all-includes', + '--sp-file', concatenated_rules, + '--patch', meson.project_source_root(), + '@INPUT@', + ], + input: meson.project_source_root() / source, + output: source.underscorify() + '.patch', + capture: true, + depend_files: headers, + ) +endforeach + +concatenated_patch = custom_target( + command: [ + 'cat', '@INPUT@', + ], + input: patches, + output: 'cocci.patch', + capture: true, +) + +alias_target('coccicheck', concatenated_patch) diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index b3b6aa3bae..413911be3b 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -2737,12 +2737,17 @@ __git_compute_config_vars_all () __git_config_vars_all="$(git --no-pager help --config)" } +__git_indirect() +{ + eval printf '%s' "\"\$$1\"" +} + __git_compute_first_level_config_vars_for_section () { local section="$1" __git_compute_config_vars local this_section="__git_first_level_config_vars_for_section_${section}" - test -n "${!this_section}" || + test -n "$(__git_indirect "${this_section}")" || printf -v "__git_first_level_config_vars_for_section_${section}" %s \ "$(echo "$__git_config_vars" | awk -F. "/^${section}\.[a-z]/ { print \$2 }")" } @@ -2752,7 +2757,7 @@ __git_compute_second_level_config_vars_for_section () local section="$1" __git_compute_config_vars_all local this_section="__git_second_level_config_vars_for_section_${section}" - test -n "${!this_section}" || + test -n "$(__git_indirect "${this_section}")" || printf -v "__git_second_level_config_vars_for_section_${section}" %s \ "$(echo "$__git_config_vars_all" | awk -F. "/^${section}\.</ { print \$3 }")" } @@ -2907,7 +2912,7 @@ __git_complete_config_variable_name () local section="${pfx%.*.}" __git_compute_second_level_config_vars_for_section "${section}" local this_section="__git_second_level_config_vars_for_section_${section}" - __gitcomp "${!this_section}" "$pfx" "$cur_" "$sfx" + __gitcomp "$(__git_indirect "${this_section}")" "$pfx" "$cur_" "$sfx" return ;; branch.*) @@ -2917,7 +2922,7 @@ __git_complete_config_variable_name () __gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")" __git_compute_first_level_config_vars_for_section "${section}" local this_section="__git_first_level_config_vars_for_section_${section}" - __gitcomp_nl_append "${!this_section}" "$pfx" "$cur_" "${sfx:- }" + __gitcomp_nl_append "$(__git_indirect "${this_section}")" "$pfx" "$cur_" "${sfx:- }" return ;; pager.*) @@ -2934,7 +2939,7 @@ __git_complete_config_variable_name () __gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "." __git_compute_first_level_config_vars_for_section "${section}" local this_section="__git_first_level_config_vars_for_section_${section}" - __gitcomp_nl_append "${!this_section}" "$pfx" "$cur_" "${sfx:- }" + __gitcomp_nl_append "$(__git_indirect "${this_section}")" "$pfx" "$cur_" "${sfx:- }" return ;; submodule.*) @@ -2944,7 +2949,7 @@ __git_complete_config_variable_name () __gitcomp_nl "$(__git config -f "$(__git rev-parse --show-toplevel)/.gitmodules" --get-regexp 'submodule.*.path' | awk -F. '{print $2}')" "$pfx" "$cur_" "." __git_compute_first_level_config_vars_for_section "${section}" local this_section="__git_first_level_config_vars_for_section_${section}" - __gitcomp_nl_append "${!this_section}" "$pfx" "$cur_" "${sfx:- }" + __gitcomp_nl_append "$(__git_indirect "${this_section}")" "$pfx" "$cur_" "${sfx:- }" return ;; *.*) diff --git a/contrib/contacts/Makefile b/contrib/contacts/Makefile index a2990f0dcb..9c4ca4f3bc 100644 --- a/contrib/contacts/Makefile +++ b/contrib/contacts/Makefile @@ -34,7 +34,7 @@ GIT_CONTACTS := git-contacts GIT_CONTACTS_DOC := git-contacts.1 GIT_CONTACTS_XML := git-contacts.xml -GIT_CONTACTS_TXT := git-contacts.txt +GIT_CONTACTS_TXT := git-contacts.adoc GIT_CONTACTS_HTML := git-contacts.html doc: $(GIT_CONTACTS_DOC) $(GIT_CONTACTS_HTML) diff --git a/contrib/contacts/git-contacts.txt b/contrib/contacts/git-contacts.adoc index dd914d1261..dd914d1261 100644 --- a/contrib/contacts/git-contacts.txt +++ b/contrib/contacts/git-contacts.adoc diff --git a/contrib/contacts/meson.build b/contrib/contacts/meson.build new file mode 100644 index 0000000000..73d82dfe52 --- /dev/null +++ b/contrib/contacts/meson.build @@ -0,0 +1,55 @@ +custom_target( + input: 'git-contacts', + output: 'git-contacts', + command: generate_perl_command, + depends: [git_version_file], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +if get_option('docs').contains('man') + contacts_xml = custom_target( + command: asciidoc_common_options + [ + '--backend=' + asciidoc_docbook, + '--doctype=manpage', + '--out-file=@OUTPUT@', + '@INPUT@', + ], + depends: documentation_deps, + input: 'git-contacts.adoc', + output: 'git-contacts.xml', + ) + + custom_target( + command: [ + xmlto, + '-m', '@INPUT@', + 'man', + contacts_xml, + '-o', + meson.current_build_dir(), + ] + xmlto_extra, + input: [ + '../../Documentation/manpage-normal.xsl', + ], + output: 'git-contacts.1', + install: true, + install_dir: get_option('mandir') / 'man1', + ) +endif + +if get_option('docs').contains('html') + custom_target( + command: asciidoc_common_options + [ + '--backend=' + asciidoc_html, + '--doctype=manpage', + '--out-file=@OUTPUT@', + '@INPUT@', + ], + depends: documentation_deps, + input: 'git-contacts.adoc', + output: 'git-contacts.html', + install: true, + install_dir: get_option('datadir') / 'doc/git-doc', + ) +endif diff --git a/contrib/credential/libsecret/Makefile b/contrib/credential/libsecret/Makefile index 3e67552cc5..97ce9c92fb 100644 --- a/contrib/credential/libsecret/Makefile +++ b/contrib/credential/libsecret/Makefile @@ -1,3 +1,6 @@ +# The default target of this Makefile is... +all:: + MAIN:=git-credential-libsecret all:: $(MAIN) diff --git a/contrib/credential/libsecret/git-credential-libsecret.c b/contrib/credential/libsecret/git-credential-libsecret.c index 90034d0cf1..941b2afd5e 100644 --- a/contrib/credential/libsecret/git-credential-libsecret.c +++ b/contrib/credential/libsecret/git-credential-libsecret.c @@ -59,10 +59,10 @@ static void credential_clear(struct credential *c); /* ----------------- Secret Service functions ----------------- */ static const SecretSchema schema = { - "org.git.Password", + .name = "org.git.Password", /* Ignore schema name during search for backwards compatibility */ - SECRET_SCHEMA_DONT_MATCH_NAME, - { + .flags = SECRET_SCHEMA_DONT_MATCH_NAME, + .attributes = { /* * libsecret assumes attribute values are non-confidential and * unchanging, so we can't include oauth_refresh_token or @@ -168,7 +168,7 @@ static int keyring_get(struct credential *c) g_free(c->password); c->password = g_strdup(""); } - for (int i = 1; i < g_strv_length(parts); i++) { + for (guint i = 1; i < g_strv_length(parts); i++) { if (g_str_has_prefix(parts[i], "password_expiry_utc=")) { g_free(c->password_expiry_utc); c->password_expiry_utc = g_strdup(&parts[i][20]); @@ -424,7 +424,7 @@ int main(int argc, char *argv[]) struct credential_operation const *try_op = credential_helper_ops; struct credential cred = CREDENTIAL_INIT; - if (!argv[1]) { + if (argc < 2 || !*argv[1]) { usage(argv[0]); exit(EXIT_FAILURE); } diff --git a/contrib/credential/libsecret/meson.build b/contrib/credential/libsecret/meson.build new file mode 100644 index 0000000000..0137660fe0 --- /dev/null +++ b/contrib/credential/libsecret/meson.build @@ -0,0 +1,9 @@ +executable('git-credential-libsecret', + sources: 'git-credential-libsecret.c', + dependencies: [ + dependency('glib-2.0'), + dependency('libsecret-1'), + ], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) diff --git a/contrib/credential/meson.build b/contrib/credential/meson.build new file mode 100644 index 0000000000..4216296ae0 --- /dev/null +++ b/contrib/credential/meson.build @@ -0,0 +1,3 @@ +foreach helper : get_option('credential_helpers') + subdir(helper) +endforeach diff --git a/contrib/credential/netrc/meson.build b/contrib/credential/netrc/meson.build new file mode 100644 index 0000000000..a990dbb86d --- /dev/null +++ b/contrib/credential/netrc/meson.build @@ -0,0 +1,20 @@ +credential_netrc = custom_target( + input: 'git-credential-netrc.perl', + output: 'git-credential-netrc', + command: generate_perl_command, + depends: [git_version_file], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +credential_netrc_testenv = test_environment +credential_netrc_testenv.set('CREDENTIAL_NETRC_PATH', credential_netrc.full_path()) + +test('t-git-credential-netrc', + shell, + args: [ meson.current_source_dir() / 't-git-credential-netrc.sh' ], + workdir: meson.current_source_dir(), + env: credential_netrc_testenv, + depends: test_dependencies + bin_wrappers + [credential_netrc], + timeout: 0, +) diff --git a/contrib/credential/netrc/t-git-credential-netrc.sh b/contrib/credential/netrc/t-git-credential-netrc.sh index bf2777308a..1b7b8b3a9a 100755 --- a/contrib/credential/netrc/t-git-credential-netrc.sh +++ b/contrib/credential/netrc/t-git-credential-netrc.sh @@ -15,7 +15,7 @@ export PERL5LIB="$GITPERLLIB" test_expect_success 'git-credential-netrc' ' - perl "$GIT_BUILD_DIR"/contrib/credential/netrc/test.pl + perl "$GIT_SOURCE_DIR"/contrib/credential/netrc/test.pl ' test_done diff --git a/contrib/credential/netrc/test.pl b/contrib/credential/netrc/test.pl index c0fb3718b2..67a0ede564 100755 --- a/contrib/credential/netrc/test.pl +++ b/contrib/credential/netrc/test.pl @@ -15,10 +15,11 @@ BEGIN { my @global_credential_args = @ARGV; my $scriptDir = dirname rel2abs $0; -my ($netrc, $netrcGpg, $gcNetrc) = map { catfile $scriptDir, $_; } +my ($netrc, $netrcGpg) = map { catfile $scriptDir, $_; } qw(test.netrc - test.netrc.gpg - git-credential-netrc); + test.netrc.gpg); +my $gcNetrc = $ENV{CREDENTIAL_NETRC_PATH} || catfile $scriptDir, qw(git-credential-netrc); + local $ENV{PATH} = join ':' , $scriptDir , $ENV{PATH} diff --git a/contrib/credential/osxkeychain/Makefile b/contrib/credential/osxkeychain/Makefile index 238f5f8c36..0948297e20 100644 --- a/contrib/credential/osxkeychain/Makefile +++ b/contrib/credential/osxkeychain/Makefile @@ -1,3 +1,4 @@ +# The default target of this Makefile is... all:: git-credential-osxkeychain CC = gcc diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c b/contrib/credential/osxkeychain/git-credential-osxkeychain.c index 1c8310d7fe..611c9798b3 100644 --- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c +++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c @@ -422,7 +422,7 @@ int main(int argc, const char **argv) const char *usage = "usage: git credential-osxkeychain <get|store|erase>"; - if (!argv[1]) + if (argc < 2 || !*argv[1]) die("%s", usage); if (open(argv[0], O_RDONLY | O_EXLOCK) == -1) diff --git a/contrib/credential/osxkeychain/meson.build b/contrib/credential/osxkeychain/meson.build new file mode 100644 index 0000000000..3c7677f736 --- /dev/null +++ b/contrib/credential/osxkeychain/meson.build @@ -0,0 +1,9 @@ +executable('git-credential-osxkeychain', + sources: 'git-credential-osxkeychain.c', + dependencies: [ + dependency('CoreFoundation'), + dependency('Security'), + ], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) diff --git a/contrib/credential/wincred/Makefile b/contrib/credential/wincred/Makefile index 6e992c0866..5b795fc9fe 100644 --- a/contrib/credential/wincred/Makefile +++ b/contrib/credential/wincred/Makefile @@ -1,4 +1,5 @@ -all: git-credential-wincred.exe +# The default target of this Makefile is... +all:: git-credential-wincred.exe -include ../../../config.mak.autogen -include ../../../config.mak diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c index 4be0d58cd8..04145b5118 100644 --- a/contrib/credential/wincred/git-credential-wincred.c +++ b/contrib/credential/wincred/git-credential-wincred.c @@ -12,7 +12,9 @@ #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) +#ifndef _MSC_VER __attribute__((format (printf, 1, 2))) +#endif static void die(const char *err, ...) { char msg[4096]; diff --git a/contrib/credential/wincred/meson.build b/contrib/credential/wincred/meson.build new file mode 100644 index 0000000000..6de23ca17d --- /dev/null +++ b/contrib/credential/wincred/meson.build @@ -0,0 +1,5 @@ +executable('git-credential-wincred', + sources: 'git-credential-wincred.c', + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) diff --git a/contrib/diff-highlight/Makefile b/contrib/diff-highlight/Makefile index f2be7cc924..33c2ccc9f7 100644 --- a/contrib/diff-highlight/Makefile +++ b/contrib/diff-highlight/Makefile @@ -1,4 +1,5 @@ -all: diff-highlight +# The default target of this Makefile is... +all:: diff-highlight PERL_PATH = /usr/bin/perl -include ../../config.mak diff --git a/contrib/diff-highlight/t/Makefile b/contrib/diff-highlight/t/Makefile index 5ff5275496..2a98541477 100644 --- a/contrib/diff-highlight/t/Makefile +++ b/contrib/diff-highlight/t/Makefile @@ -1,3 +1,6 @@ +# The default target of this Makefile is... +all:: + -include ../../../config.mak.autogen -include ../../../config.mak @@ -6,7 +9,7 @@ SHELL_PATH ?= $(SHELL) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh) -all: test +all:: test test: $(T) .PHONY: help clean all test $(T) diff --git a/contrib/libgit-rs/Cargo.lock b/contrib/libgit-rs/Cargo.lock new file mode 100644 index 0000000000..a30c7c8d33 --- /dev/null +++ b/contrib/libgit-rs/Cargo.lock @@ -0,0 +1,77 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "cc" +version = "1.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +dependencies = [ + "shlex", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "libgit" +version = "0.1.0" +dependencies = [ + "autocfg", + "libgit-sys", +] + +[[package]] +name = "libgit-sys" +version = "0.1.0" +dependencies = [ + "autocfg", + "libz-sys", + "make-cmd", +] + +[[package]] +name = "libz-sys" +version = "1.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "make-cmd" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" diff --git a/contrib/libgit-rs/Cargo.toml b/contrib/libgit-rs/Cargo.toml new file mode 100644 index 0000000000..c3289e69db --- /dev/null +++ b/contrib/libgit-rs/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "libgit" +version = "0.1.0" +edition = "2021" +build = "build.rs" +rust-version = "1.63" # TODO: Once we hit 1.84 or newer, we may want to remove Cargo.lock from + # version control. See https://lore.kernel.org/git/Z47jgK-oMjFRSslr@tapette.crustytoothpaste.net/ + + +[lib] +path = "src/lib.rs" + +[dependencies] +libgit-sys = { version = "0.1.0", path = "../libgit-sys" } + +[build-dependencies] +autocfg = "1.4.0" diff --git a/contrib/libgit-rs/README.md b/contrib/libgit-rs/README.md new file mode 100644 index 0000000000..ff945e1ce2 --- /dev/null +++ b/contrib/libgit-rs/README.md @@ -0,0 +1,13 @@ +# libgit-rs + +Proof-of-concept Git bindings for Rust. + +```toml +[dependencies] +libgit = "0.1.0" +``` + +## Rust version requirements + +libgit-rs should support Rust versions at least as old as the version included +in Debian stable (currently 1.63). diff --git a/contrib/libgit-rs/build.rs b/contrib/libgit-rs/build.rs new file mode 100644 index 0000000000..f8bd01a690 --- /dev/null +++ b/contrib/libgit-rs/build.rs @@ -0,0 +1,4 @@ +pub fn main() { + let ac = autocfg::new(); + ac.emit_has_path("std::ffi::c_char"); +} diff --git a/contrib/libgit-rs/src/config.rs b/contrib/libgit-rs/src/config.rs new file mode 100644 index 0000000000..6bf04845c8 --- /dev/null +++ b/contrib/libgit-rs/src/config.rs @@ -0,0 +1,106 @@ +use std::ffi::{c_void, CStr, CString}; +use std::path::Path; + +#[cfg(has_std__ffi__c_char)] +use std::ffi::{c_char, c_int}; + +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +type c_char = i8; + +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +type c_int = i32; + +use libgit_sys::*; + +/// A ConfigSet is an in-memory cache for config-like files such as `.gitmodules` or `.gitconfig`. +/// It does not support all config directives; notably, it will not process `include` or +/// `includeIf` directives (but it will store them so that callers can choose whether and how to +/// handle them). +pub struct ConfigSet(*mut libgit_config_set); +impl ConfigSet { + /// Allocate a new ConfigSet + pub fn new() -> Self { + unsafe { ConfigSet(libgit_configset_alloc()) } + } + + /// Load the given files into the ConfigSet; conflicting directives in later files will + /// override those given in earlier files. + pub fn add_files(&mut self, files: &[&Path]) { + for file in files { + let pstr = file.to_str().expect("Invalid UTF-8"); + let rs = CString::new(pstr).expect("Couldn't convert to CString"); + unsafe { + libgit_configset_add_file(self.0, rs.as_ptr()); + } + } + } + + /// Load the value for the given key and attempt to parse it as an i32. Dies with a fatal error + /// if the value cannot be parsed. Returns None if the key is not present. + pub fn get_int(&mut self, key: &str) -> Option<i32> { + let key = CString::new(key).expect("Couldn't convert to CString"); + let mut val: c_int = 0; + unsafe { + if libgit_configset_get_int(self.0, key.as_ptr(), &mut val as *mut c_int) != 0 { + return None; + } + } + + Some(val.into()) + } + + /// Clones the value for the given key. Dies with a fatal error if the value cannot be + /// converted to a String. Returns None if the key is not present. + pub fn get_string(&mut self, key: &str) -> Option<String> { + let key = CString::new(key).expect("Couldn't convert key to CString"); + let mut val: *mut c_char = std::ptr::null_mut(); + unsafe { + if libgit_configset_get_string(self.0, key.as_ptr(), &mut val as *mut *mut c_char) != 0 + { + return None; + } + let borrowed_str = CStr::from_ptr(val); + let owned_str = + String::from(borrowed_str.to_str().expect("Couldn't convert val to str")); + free(val as *mut c_void); // Free the xstrdup()ed pointer from the C side + Some(owned_str) + } + } +} + +impl Default for ConfigSet { + fn default() -> Self { + Self::new() + } +} + +impl Drop for ConfigSet { + fn drop(&mut self) { + unsafe { + libgit_configset_free(self.0); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn load_configs_via_configset() { + let mut cs = ConfigSet::new(); + cs.add_files(&[ + Path::new("testdata/config1"), + Path::new("testdata/config2"), + Path::new("testdata/config3"), + ]); + // ConfigSet retrieves correct value + assert_eq!(cs.get_int("trace2.eventTarget"), Some(1)); + // ConfigSet respects last config value set + assert_eq!(cs.get_int("trace2.eventNesting"), Some(3)); + // ConfigSet returns None for missing key + assert_eq!(cs.get_string("foo.bar"), None); + } +} diff --git a/contrib/libgit-rs/src/lib.rs b/contrib/libgit-rs/src/lib.rs new file mode 100644 index 0000000000..ef68c36943 --- /dev/null +++ b/contrib/libgit-rs/src/lib.rs @@ -0,0 +1 @@ +pub mod config; diff --git a/contrib/libgit-rs/testdata/config1 b/contrib/libgit-rs/testdata/config1 new file mode 100644 index 0000000000..4e9a9d25d1 --- /dev/null +++ b/contrib/libgit-rs/testdata/config1 @@ -0,0 +1,2 @@ +[trace2] + eventNesting = 1 diff --git a/contrib/libgit-rs/testdata/config2 b/contrib/libgit-rs/testdata/config2 new file mode 100644 index 0000000000..b8d1eca423 --- /dev/null +++ b/contrib/libgit-rs/testdata/config2 @@ -0,0 +1,2 @@ +[trace2] + eventTarget = 1 diff --git a/contrib/libgit-rs/testdata/config3 b/contrib/libgit-rs/testdata/config3 new file mode 100644 index 0000000000..ca7b9a7c38 --- /dev/null +++ b/contrib/libgit-rs/testdata/config3 @@ -0,0 +1,2 @@ +[trace2] + eventNesting = 3 diff --git a/contrib/libgit-sys/Cargo.lock b/contrib/libgit-sys/Cargo.lock new file mode 100644 index 0000000000..427a4c66b7 --- /dev/null +++ b/contrib/libgit-sys/Cargo.lock @@ -0,0 +1,69 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "cc" +version = "1.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +dependencies = [ + "shlex", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "libgit-sys" +version = "0.1.0" +dependencies = [ + "autocfg", + "libz-sys", + "make-cmd", +] + +[[package]] +name = "libz-sys" +version = "1.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "make-cmd" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" diff --git a/contrib/libgit-sys/Cargo.toml b/contrib/libgit-sys/Cargo.toml new file mode 100644 index 0000000000..e0623022c3 --- /dev/null +++ b/contrib/libgit-sys/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "libgit-sys" +version = "0.1.0" +edition = "2021" +build = "build.rs" +links = "gitpub" +rust-version = "1.63" # TODO: Once we hit 1.84 or newer, we may want to remove Cargo.lock from + # version control. See https://lore.kernel.org/git/Z47jgK-oMjFRSslr@tapette.crustytoothpaste.net/ +description = "Native bindings to a portion of libgit" + +[lib] +path = "src/lib.rs" + +[dependencies] +libz-sys = "1.1.19" + +[build-dependencies] +autocfg = "1.4.0" +make-cmd = "0.1.0" diff --git a/contrib/libgit-sys/README.md b/contrib/libgit-sys/README.md new file mode 100644 index 0000000000..c061cfcaf5 --- /dev/null +++ b/contrib/libgit-sys/README.md @@ -0,0 +1,4 @@ +# libgit-sys + +A small proof-of-concept crate showing how to provide a Rust FFI to Git +internals. diff --git a/contrib/libgit-sys/build.rs b/contrib/libgit-sys/build.rs new file mode 100644 index 0000000000..3ffd80ad91 --- /dev/null +++ b/contrib/libgit-sys/build.rs @@ -0,0 +1,35 @@ +use std::env; +use std::path::PathBuf; + +pub fn main() -> std::io::Result<()> { + let ac = autocfg::new(); + ac.emit_has_path("std::ffi::c_char"); + + let crate_root = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); + let git_root = crate_root.join("../.."); + let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + let make_output = make_cmd::gnu_make() + .env("DEVELOPER", "1") + .env_remove("PROFILE") + .current_dir(git_root.clone()) + .args([ + "INCLUDE_LIBGIT_RS=YesPlease", + "contrib/libgit-sys/libgitpub.a", + ]) + .output() + .expect("Make failed to run"); + if !make_output.status.success() { + panic!( + "Make failed:\n stdout = {}\n stderr = {}\n", + String::from_utf8(make_output.stdout).unwrap(), + String::from_utf8(make_output.stderr).unwrap() + ); + } + std::fs::copy(crate_root.join("libgitpub.a"), dst.join("libgitpub.a"))?; + println!("cargo:rustc-link-search=native={}", dst.display()); + println!("cargo:rustc-link-lib=gitpub"); + println!("cargo:rerun-if-changed={}", git_root.display()); + + Ok(()) +} diff --git a/contrib/libgit-sys/public_symbol_export.c b/contrib/libgit-sys/public_symbol_export.c new file mode 100644 index 0000000000..dfbb257115 --- /dev/null +++ b/contrib/libgit-sys/public_symbol_export.c @@ -0,0 +1,59 @@ +/* + * Shim to publicly export Git symbols. These must be renamed so that the + * original symbols can be hidden. Renaming these with a "libgit_" prefix also + * avoids conflicts with other libraries such as libgit2. + */ + +#include "git-compat-util.h" +#include "config.h" +#include "contrib/libgit-sys/public_symbol_export.h" +#include "version.h" + +#pragma GCC visibility push(default) + +struct libgit_config_set { + struct config_set cs; +}; + +struct libgit_config_set *libgit_configset_alloc(void) +{ + struct libgit_config_set *cs = + xmalloc(sizeof(struct libgit_config_set)); + git_configset_init(&cs->cs); + return cs; +} + +void libgit_configset_free(struct libgit_config_set *cs) +{ + git_configset_clear(&cs->cs); + free(cs); +} + +int libgit_configset_add_file(struct libgit_config_set *cs, const char *filename) +{ + return git_configset_add_file(&cs->cs, filename); +} + +int libgit_configset_get_int(struct libgit_config_set *cs, const char *key, + int *dest) +{ + return git_configset_get_int(&cs->cs, key, dest); +} + +int libgit_configset_get_string(struct libgit_config_set *cs, const char *key, + char **dest) +{ + return git_configset_get_string(&cs->cs, key, dest); +} + +const char *libgit_user_agent(void) +{ + return git_user_agent(); +} + +const char *libgit_user_agent_sanitized(void) +{ + return git_user_agent_sanitized(); +} + +#pragma GCC visibility pop diff --git a/contrib/libgit-sys/public_symbol_export.h b/contrib/libgit-sys/public_symbol_export.h new file mode 100644 index 0000000000..701db92d53 --- /dev/null +++ b/contrib/libgit-sys/public_symbol_export.h @@ -0,0 +1,18 @@ +#ifndef PUBLIC_SYMBOL_EXPORT_H +#define PUBLIC_SYMBOL_EXPORT_H + +struct libgit_config_set *libgit_configset_alloc(void); + +void libgit_configset_free(struct libgit_config_set *cs); + +int libgit_configset_add_file(struct libgit_config_set *cs, const char *filename); + +int libgit_configset_get_int(struct libgit_config_set *cs, const char *key, int *dest); + +int libgit_configset_get_string(struct libgit_config_set *cs, const char *key, char **dest); + +const char *libgit_user_agent(void); + +const char *libgit_user_agent_sanitized(void); + +#endif /* PUBLIC_SYMBOL_EXPORT_H */ diff --git a/contrib/libgit-sys/src/lib.rs b/contrib/libgit-sys/src/lib.rs new file mode 100644 index 0000000000..4bfc650450 --- /dev/null +++ b/contrib/libgit-sys/src/lib.rs @@ -0,0 +1,79 @@ +use std::ffi::c_void; + +#[cfg(has_std__ffi__c_char)] +use std::ffi::{c_char, c_int}; + +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +pub type c_char = i8; + +#[cfg(not(has_std__ffi__c_char))] +#[allow(non_camel_case_types)] +pub type c_int = i32; + +extern crate libz_sys; + +#[allow(non_camel_case_types)] +#[repr(C)] +pub struct libgit_config_set { + _data: [u8; 0], + _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, +} + +extern "C" { + pub fn free(ptr: *mut c_void); + + pub fn libgit_user_agent() -> *const c_char; + pub fn libgit_user_agent_sanitized() -> *const c_char; + + pub fn libgit_configset_alloc() -> *mut libgit_config_set; + pub fn libgit_configset_free(cs: *mut libgit_config_set); + + pub fn libgit_configset_add_file(cs: *mut libgit_config_set, filename: *const c_char) -> c_int; + + pub fn libgit_configset_get_int( + cs: *mut libgit_config_set, + key: *const c_char, + int: *mut c_int, + ) -> c_int; + + pub fn libgit_configset_get_string( + cs: *mut libgit_config_set, + key: *const c_char, + dest: *mut *mut c_char, + ) -> c_int; + +} + +#[cfg(test)] +mod tests { + use std::ffi::CStr; + + use super::*; + + #[test] + fn user_agent_starts_with_git() { + let c_str = unsafe { CStr::from_ptr(libgit_user_agent()) }; + let agent = c_str + .to_str() + .expect("User agent contains invalid UTF-8 data"); + assert!( + agent.starts_with("git/"), + r#"Expected user agent to start with "git/", got: {}"#, + agent + ); + } + + #[test] + fn sanitized_user_agent_starts_with_git() { + let c_str = unsafe { CStr::from_ptr(libgit_user_agent_sanitized()) }; + let agent = c_str + .to_str() + .expect("Sanitized user agent contains invalid UTF-8 data"); + assert!( + agent.starts_with("git/"), + r#"Expected user agent to start with "git/", got: {}"#, + agent + ); + } +} diff --git a/contrib/long-running-filter/example.pl b/contrib/long-running-filter/example.pl index a677569ddd..4b83e4c5e8 100755 --- a/contrib/long-running-filter/example.pl +++ b/contrib/long-running-filter/example.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl # # Example implementation for the Git filter protocol version 2 -# See Documentation/gitattributes.txt, section "Filter Protocol" +# See Documentation/gitattributes.adoc, section "Filter Protocol" # # Please note, this pass-thru filter is a minimal skeleton. No proper # error handling was implemented. diff --git a/contrib/meson.build b/contrib/meson.build index a7b77b87c2..a88c5dfe09 100644 --- a/contrib/meson.build +++ b/contrib/meson.build @@ -1 +1,6 @@ -subdir('completion') +foreach feature : get_option('contrib') + subdir(feature) +endforeach + +subdir('coccinelle') +subdir('credential') diff --git a/contrib/mw-to-git/Makefile b/contrib/mw-to-git/Makefile index 4e603512a3..497ac434d6 100644 --- a/contrib/mw-to-git/Makefile +++ b/contrib/mw-to-git/Makefile @@ -12,6 +12,9 @@ # # make install +# The default target of this Makefile is... +all:: + GIT_MEDIAWIKI_PM=Git/Mediawiki.pm SCRIPT_PERL=git-remote-mediawiki.perl SCRIPT_PERL+=git-mw.perl @@ -27,7 +30,7 @@ INSTLIBDIR=$(shell $(MAKE) -C $(GIT_ROOT_DIR)/ \ DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) INSTLIBDIR_SQ = $(subst ','\'',$(INSTLIBDIR)) -all: build +all:: build test: all $(MAKE) -C t diff --git a/contrib/mw-to-git/t/Makefile b/contrib/mw-to-git/t/Makefile index f422203fa0..6c9f377caa 100644 --- a/contrib/mw-to-git/t/Makefile +++ b/contrib/mw-to-git/t/Makefile @@ -8,7 +8,8 @@ # ## Test git-remote-mediawiki -all: test +# The default target of this Makefile is... +all:: test -include ../../../config.mak.autogen -include ../../../config.mak diff --git a/contrib/persistent-https/Makefile b/contrib/persistent-https/Makefile index 52b84ba3d4..691737e76b 100644 --- a/contrib/persistent-https/Makefile +++ b/contrib/persistent-https/Makefile @@ -12,10 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +# The default target of this Makefile is... +all:: + BUILD_LABEL=$(shell cut -d" " -f3 ../../GIT-VERSION-FILE) TAR_OUT=$(shell go env GOOS)_$(shell go env GOARCH).tar.gz -all: git-remote-persistent-https git-remote-persistent-https--proxy \ +all:: git-remote-persistent-https git-remote-persistent-https--proxy \ git-remote-persistent-http git-remote-persistent-https--proxy: git-remote-persistent-https diff --git a/contrib/subtree/.gitignore b/contrib/subtree/.gitignore index 0b9381abca..6deaf177c7 100644 --- a/contrib/subtree/.gitignore +++ b/contrib/subtree/.gitignore @@ -1,4 +1,6 @@ *~ +asciidoc.conf +asciidoctor-extensions.rb git-subtree git-subtree.1 git-subtree.html diff --git a/contrib/subtree/Makefile b/contrib/subtree/Makefile index 6fa7496bfd..c0c9f21cb7 100644 --- a/contrib/subtree/Makefile +++ b/contrib/subtree/Makefile @@ -1,6 +1,7 @@ # The default target of this Makefile is... all:: +-include ../../shared.mak -include ../../config.mak.autogen -include ../../config.mak @@ -13,17 +14,16 @@ htmldir ?= $(prefix)/share/doc/git-doc ../../GIT-VERSION-FILE: FORCE $(MAKE) -C ../../ GIT-VERSION-FILE --include ../../GIT-VERSION-FILE - # this should be set to a 'standard' bsd-type install program INSTALL ?= install RM ?= rm -f ASCIIDOC = asciidoc -ASCIIDOC_CONF = -f ../../Documentation/asciidoc.conf +ASCIIDOC_CONF = -f asciidoc.conf ASCIIDOC_HTML = xhtml11 ASCIIDOC_DOCBOOK = docbook ASCIIDOC_EXTRA = +ASCIIDOC_DEPS = asciidoc.conf XMLTO = xmlto XMLTO_EXTRA = @@ -32,8 +32,9 @@ ASCIIDOC = asciidoctor ASCIIDOC_CONF = ASCIIDOC_HTML = xhtml5 ASCIIDOC_DOCBOOK = docbook -ASCIIDOC_EXTRA += -I../../Documentation -rasciidoctor-extensions +ASCIIDOC_EXTRA += -I. -rasciidoctor-extensions ASCIIDOC_EXTRA += -alitdd='&\#x2d;&\#x2d;' +ASCIIDOC_DEPS = asciidoctor-extensions.rb XMLTO_EXTRA += --skip-validation endif @@ -49,7 +50,7 @@ GIT_SUBTREE := git-subtree GIT_SUBTREE_DOC := git-subtree.1 GIT_SUBTREE_XML := git-subtree.xml -GIT_SUBTREE_TXT := git-subtree.txt +GIT_SUBTREE_TXT := git-subtree.adoc GIT_SUBTREE_HTML := git-subtree.html GIT_SUBTREE_TEST := ../../git-subtree @@ -82,13 +83,13 @@ install-html: $(GIT_SUBTREE_HTML) $(GIT_SUBTREE_DOC): $(GIT_SUBTREE_XML) $(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $^ -$(GIT_SUBTREE_XML): $(GIT_SUBTREE_TXT) +$(GIT_SUBTREE_XML): $(GIT_SUBTREE_TXT) $(ASCIIDOC_DEPS) $(ASCIIDOC) -b $(ASCIIDOC_DOCBOOK) -d manpage $(ASCIIDOC_CONF) \ - -agit_version=$(GIT_VERSION) $(ASCIIDOC_EXTRA) $^ + $(ASCIIDOC_EXTRA) $< -$(GIT_SUBTREE_HTML): $(GIT_SUBTREE_TXT) +$(GIT_SUBTREE_HTML): $(GIT_SUBTREE_TXT) $(ASCIIDOC_DEPS) $(ASCIIDOC) -b $(ASCIIDOC_HTML) -d manpage $(ASCIIDOC_CONF) \ - -agit_version=$(GIT_VERSION) $(ASCIIDOC_EXTRA) $^ + $(ASCIIDOC_EXTRA) $< $(GIT_SUBTREE_TEST): $(GIT_SUBTREE) cp $< $@ @@ -98,6 +99,12 @@ test: $(GIT_SUBTREE_TEST) clean: $(RM) $(GIT_SUBTREE) + $(RM) asciidoc.conf asciidoctor-extensions.rb $(RM) *.xml *.html *.1 +asciidoc.conf: ../../Documentation/asciidoc.conf.in ../../GIT-VERSION-FILE + $(QUIET_GEN)$(call version_gen,"$(shell pwd)/../..",$<,$@) +asciidoctor-extensions.rb: ../../Documentation/asciidoctor-extensions.rb.in ../../GIT-VERSION-FILE + $(QUIET_GEN)$(call version_gen,"$(shell pwd)/../..",$<,$@) + .PHONY: FORCE diff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.adoc index 004abf415b..004abf415b 100644 --- a/contrib/subtree/git-subtree.txt +++ b/contrib/subtree/git-subtree.adoc diff --git a/contrib/subtree/meson.build b/contrib/subtree/meson.build new file mode 100644 index 0000000000..9c72b23625 --- /dev/null +++ b/contrib/subtree/meson.build @@ -0,0 +1,71 @@ +git_subtree = custom_target( + input: 'git-subtree.sh', + output: 'git-subtree', + command: [ + shell, + meson.project_source_root() / 'generate-script.sh', + '@INPUT@', + '@OUTPUT@', + meson.project_build_root() / 'GIT-BUILD-OPTIONS', + ], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +subtree_test_environment = test_environment +subtree_test_environment.prepend('PATH', meson.current_build_dir()) + +test('t7900-subtree', shell, + args: [ 't7900-subtree.sh' ], + env: subtree_test_environment, + workdir: meson.current_source_dir() / 't', + depends: test_dependencies + bin_wrappers + [ git_subtree ], + timeout: 0, +) + +if get_option('docs').contains('man') + subtree_xml = custom_target( + command: asciidoc_common_options + [ + '--backend=' + asciidoc_docbook, + '--doctype=manpage', + '--out-file=@OUTPUT@', + '@INPUT@', + ], + depends: documentation_deps, + input: 'git-subtree.adoc', + output: 'git-subtree.xml', + ) + + custom_target( + command: [ + xmlto, + '-m', '@INPUT@', + 'man', + subtree_xml, + '-o', + meson.current_build_dir(), + ] + xmlto_extra, + input: [ + '../../Documentation/manpage-normal.xsl', + ], + output: 'git-subtree.1', + install: true, + install_dir: get_option('mandir') / 'man1', + ) +endif + +if get_option('docs').contains('html') + custom_target( + command: asciidoc_common_options + [ + '--backend=' + asciidoc_html, + '--doctype=manpage', + '--out-file=@OUTPUT@', + '@INPUT@', + ], + depends: documentation_deps, + input: 'git-subtree.adoc', + output: 'git-subtree.html', + install: true, + install_dir: get_option('datadir') / 'doc/git-doc', + ) +endif diff --git a/contrib/subtree/t/Makefile b/contrib/subtree/t/Makefile index 093399c788..2a85f5ee84 100644 --- a/contrib/subtree/t/Makefile +++ b/contrib/subtree/t/Makefile @@ -3,6 +3,9 @@ # Copyright (c) 2005 Junio C Hamano # +# The default target of this Makefile is... +all:: + -include ../../../config.mak.autogen -include ../../../config.mak @@ -31,7 +34,7 @@ TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh)) TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh)) THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh))) -all: $(DEFAULT_TEST_TARGET) +all:: $(DEFAULT_TEST_TARGET) test: pre-clean $(TEST_LINT) $(MAKE) aggregate-results-and-cleanup diff --git a/contrib/thunderbird-patch-inline/appp.sh b/contrib/thunderbird-patch-inline/appp.sh index 1053872eea..fdcc948352 100755 --- a/contrib/thunderbird-patch-inline/appp.sh +++ b/contrib/thunderbird-patch-inline/appp.sh @@ -31,7 +31,7 @@ BODY=$(sed -e "1,/${SEP}/d" $1) CMT_MSG=$(sed -e '1,/^$/d' -e '/^---$/,$d' "${PATCH}") DIFF=$(sed -e '1,/^---$/d' "${PATCH}") -CCS=$(echo -e "$CMT_MSG\n$HEADERS" | sed -n -e 's/^Cc: \(.*\)$/\1,/gp' \ +CCS=$(printf '%s\n%s\n' "$CMT_MSG" "$HEADERS" | sed -n -e 's/^Cc: \(.*\)$/\1,/gp' \ -e 's/^Signed-off-by: \(.*\)/\1,/gp') echo "$SUBJECT" > $1 @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "copy.h" #include "path.h" @@ -57,7 +59,7 @@ int copy_file(const char *dst, const char *src, int mode) if (close(fdo) != 0) return error_errno("%s: close error", dst); - if (!status && adjust_shared_perm(dst)) + if (!status && adjust_shared_perm(the_repository, dst)) return -1; return status; diff --git a/credential.c b/credential.c index 6e6e81c4cb..2594c0c422 100644 --- a/credential.c +++ b/credential.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -170,7 +169,7 @@ static int match_partial_url(const char *url, void *cb) return matches; } -static void credential_apply_config(struct credential *c) +static void credential_apply_config(struct repository *r, struct credential *c) { char *normalized_url; struct urlmatch_config config = URLMATCH_CONFIG_INIT; @@ -195,7 +194,7 @@ static void credential_apply_config(struct credential *c) credential_format(c, &url); normalized_url = url_normalize(url.buf, &config.url); - git_config(urlmatch_config_entry, &config); + repo_config(r, urlmatch_config_entry, &config); string_list_clear(&config.vars, 1); free(normalized_url); urlmatch_config_release(&config); @@ -262,34 +261,34 @@ static char *credential_ask_one(const char *what, struct credential *c, return xstrdup(r); } -static int credential_getpass(struct credential *c) +static int credential_getpass(struct repository *r, struct credential *c) { int interactive; char *value; - if (!git_config_get_maybe_bool("credential.interactive", &interactive) && + if (!repo_config_get_maybe_bool(r, "credential.interactive", &interactive) && !interactive) { - trace2_data_intmax("credential", the_repository, + trace2_data_intmax("credential", r, "interactive/skipped", 1); return -1; } - if (!git_config_get_string("credential.interactive", &value)) { + if (!repo_config_get_string(r, "credential.interactive", &value)) { int same = !strcmp(value, "never"); free(value); if (same) { - trace2_data_intmax("credential", the_repository, + trace2_data_intmax("credential", r, "interactive/skipped", 1); return -1; } } - trace2_region_enter("credential", "interactive", the_repository); + trace2_region_enter("credential", "interactive", r); if (!c->username) c->username = credential_ask_one("Username", c, PROMPT_ASKPASS|PROMPT_ECHO); if (!c->password) c->password = credential_ask_one("Password", c, PROMPT_ASKPASS); - trace2_region_leave("credential", "interactive", the_repository); + trace2_region_leave("credential", "interactive", r); return 0; } @@ -502,7 +501,8 @@ static int credential_do(struct credential *c, const char *helper, return r; } -void credential_fill(struct credential *c, int all_capabilities) +void credential_fill(struct repository *r, + struct credential *c, int all_capabilities) { int i; @@ -512,7 +512,7 @@ void credential_fill(struct credential *c, int all_capabilities) credential_next_state(c); c->multistage = 0; - credential_apply_config(c); + credential_apply_config(r, c); if (all_capabilities) credential_set_all_capabilities(c, CREDENTIAL_OP_INITIAL); @@ -539,12 +539,12 @@ void credential_fill(struct credential *c, int all_capabilities) c->helpers.items[i].string); } - if (credential_getpass(c) || + if (credential_getpass(r, c) || (!c->username && !c->password && !c->credential)) die("unable to get password from user"); } -void credential_approve(struct credential *c) +void credential_approve(struct repository *r, struct credential *c) { int i; @@ -555,20 +555,20 @@ void credential_approve(struct credential *c) credential_next_state(c); - credential_apply_config(c); + credential_apply_config(r, c); for (i = 0; i < c->helpers.nr; i++) credential_do(c, c->helpers.items[i].string, "store"); c->approved = 1; } -void credential_reject(struct credential *c) +void credential_reject(struct repository *r, struct credential *c) { int i; credential_next_state(c); - credential_apply_config(c); + credential_apply_config(r, c); for (i = 0; i < c->helpers.nr; i++) credential_do(c, c->helpers.items[i].string, "erase"); diff --git a/credential.h b/credential.h index 63fef3e2ea..c78b72d110 100644 --- a/credential.h +++ b/credential.h @@ -4,6 +4,8 @@ #include "string-list.h" #include "strvec.h" +struct repository; + /** * The credentials API provides an abstracted way of gathering * authentication credentials from the user. @@ -65,7 +67,7 @@ * // Fill in the username and password fields by contacting * // helpers and/or asking the user. The function will die if it * // fails. - * credential_fill(&c); + * credential_fill(repo, &c); * * // Otherwise, we have a username and password. Try to use it. * @@ -222,7 +224,8 @@ void credential_clear(struct credential *); * If all_capabilities is set, this is an internal user that is prepared * to deal with all known capabilities, and we should advertise that fact. */ -void credential_fill(struct credential *, int all_capabilities); +void credential_fill(struct repository *, struct credential *, + int all_capabilities); /** * Inform the credential subsystem that the provided credentials @@ -231,7 +234,7 @@ void credential_fill(struct credential *, int all_capabilities); * that they may store the result to be used again. Any errors * from helpers are ignored. */ -void credential_approve(struct credential *); +void credential_approve(struct repository *, struct credential *); /** * Inform the credential subsystem that the provided credentials @@ -243,7 +246,7 @@ void credential_approve(struct credential *); * for another call to `credential_fill`). Any errors from helpers * are ignored. */ -void credential_reject(struct credential *); +void credential_reject(struct repository *, struct credential *); /** * Enable all of the supported credential flags in this credential. diff --git a/csum-file.c b/csum-file.c index 5716016e12..b58c183a4f 100644 --- a/csum-file.c +++ b/csum-file.c @@ -11,9 +11,10 @@ #define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" -#include "progress.h" #include "csum-file.h" +#include "git-zlib.h" #include "hash.h" +#include "progress.h" static void verify_buffer_or_die(struct hashfile *f, const void *buf, @@ -50,7 +51,7 @@ void hashflush(struct hashfile *f) if (offset) { if (!f->skip_hash) - the_hash_algo->unsafe_update_fn(&f->ctx, f->buffer, offset); + git_hash_update(&f->ctx, f->buffer, offset); flush(f, f->buffer, offset); f->offset = 0; } @@ -71,14 +72,14 @@ int finalize_hashfile(struct hashfile *f, unsigned char *result, hashflush(f); if (f->skip_hash) - hashclr(f->buffer, the_repository->hash_algo); + hashclr(f->buffer, f->algop); else - the_hash_algo->unsafe_final_fn(f->buffer, &f->ctx); + git_hash_final(f->buffer, &f->ctx); if (result) - hashcpy(result, f->buffer, the_repository->hash_algo); + hashcpy(result, f->buffer, f->algop); if (flags & CSUM_HASH_IN_STREAM) - flush(f, f->buffer, the_hash_algo->rawsz); + flush(f, f->buffer, f->algop->rawsz); if (flags & CSUM_FSYNC) fsync_component_or_die(component, f->fd, f->name); if (flags & CSUM_CLOSE) { @@ -128,7 +129,7 @@ void hashwrite(struct hashfile *f, const void *buf, unsigned int count) * f->offset is necessarily zero. */ if (!f->skip_hash) - the_hash_algo->unsafe_update_fn(&f->ctx, buf, nr); + git_hash_update(&f->ctx, buf, nr); flush(f, buf, nr); } else { /* @@ -174,7 +175,9 @@ static struct hashfile *hashfd_internal(int fd, const char *name, f->name = name; f->do_crc = 0; f->skip_hash = 0; - the_hash_algo->unsafe_init_fn(&f->ctx); + + f->algop = unsafe_hash_algo(the_hash_algo); + f->algop->init_fn(&f->ctx); f->buffer_len = buffer_len; f->buffer = xmalloc(buffer_len); @@ -204,11 +207,18 @@ struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp return hashfd_internal(fd, name, tp, 8 * 1024); } +void hashfile_checkpoint_init(struct hashfile *f, + struct hashfile_checkpoint *checkpoint) +{ + memset(checkpoint, 0, sizeof(*checkpoint)); + f->algop->init_fn(&checkpoint->ctx); +} + void hashfile_checkpoint(struct hashfile *f, struct hashfile_checkpoint *checkpoint) { hashflush(f); checkpoint->offset = f->total; - the_hash_algo->unsafe_clone_fn(&checkpoint->ctx, &f->ctx); + git_hash_clone(&checkpoint->ctx, &f->ctx); } int hashfile_truncate(struct hashfile *f, struct hashfile_checkpoint *checkpoint) @@ -219,7 +229,7 @@ int hashfile_truncate(struct hashfile *f, struct hashfile_checkpoint *checkpoint lseek(f->fd, offset, SEEK_SET) != offset) return -1; f->total = offset; - the_hash_algo->unsafe_clone_fn(&f->ctx, &checkpoint->ctx); + git_hash_clone(&f->ctx, &checkpoint->ctx); f->offset = 0; /* hashflush() was called in checkpoint */ return 0; } @@ -239,15 +249,16 @@ uint32_t crc32_end(struct hashfile *f) int hashfile_checksum_valid(const unsigned char *data, size_t total_len) { unsigned char got[GIT_MAX_RAWSZ]; - git_hash_ctx ctx; - size_t data_len = total_len - the_hash_algo->rawsz; + struct git_hash_ctx ctx; + const struct git_hash_algo *algop = unsafe_hash_algo(the_hash_algo); + size_t data_len = total_len - algop->rawsz; - if (total_len < the_hash_algo->rawsz) + if (total_len < algop->rawsz) return 0; /* say "too short"? */ - the_hash_algo->unsafe_init_fn(&ctx); - the_hash_algo->unsafe_update_fn(&ctx, data, data_len); - the_hash_algo->unsafe_final_fn(got, &ctx); + algop->init_fn(&ctx); + git_hash_update(&ctx, data, data_len); + git_hash_final(got, &ctx); - return hasheq(got, data + data_len, the_repository->hash_algo); + return hasheq(got, data + data_len, algop); } diff --git a/csum-file.h b/csum-file.h index 7c73da0a40..ffccbf0996 100644 --- a/csum-file.h +++ b/csum-file.h @@ -11,7 +11,7 @@ struct hashfile { int fd; int check_fd; unsigned int offset; - git_hash_ctx ctx; + struct git_hash_ctx ctx; off_t total; struct progress *tp; const char *name; @@ -20,6 +20,7 @@ struct hashfile { size_t buffer_len; unsigned char *buffer; unsigned char *check_buffer; + const struct git_hash_algo *algop; /** * If non-zero, skip_hash indicates that we should @@ -32,9 +33,10 @@ struct hashfile { /* Checkpoint */ struct hashfile_checkpoint { off_t offset; - git_hash_ctx ctx; + struct git_hash_ctx ctx; }; +void hashfile_checkpoint_init(struct hashfile *, struct hashfile_checkpoint *); void hashfile_checkpoint(struct hashfile *, struct hashfile_checkpoint *); int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *); @@ -1244,7 +1244,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm } for (s = special; s->name; s++) { - int len = strlen(s->name); + size_t len = strlen(s->name); if (match_string(date, s->name) == len) { s->fn(tm, now, num); *touched = 1; @@ -1254,7 +1254,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm if (!*num) { for (i = 1; i < 11; i++) { - int len = strlen(number_name[i]); + size_t len = strlen(number_name[i]); if (match_string(date, number_name[i]) == len) { *num = i; *touched = 1; @@ -1270,7 +1270,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm tl = typelen; while (tl->type) { - int len = strlen(tl->type); + size_t len = strlen(tl->type); if (match_string(date, tl->type) >= len-1) { update_tm(tm, now, tl->length * *num); *num = 0; diff --git a/decorate.c b/decorate.c index e161e13772..9f24925263 100644 --- a/decorate.c +++ b/decorate.c @@ -3,8 +3,6 @@ * data. */ -#define DISABLE_SIGN_COMPARE_WARNINGS - #include "git-compat-util.h" #include "object.h" #include "decorate.h" @@ -16,9 +14,8 @@ static unsigned int hash_obj(const struct object *obj, unsigned int n) static void *insert_decoration(struct decoration *n, const struct object *base, void *decoration) { - int size = n->size; struct decoration_entry *entries = n->entries; - unsigned int j = hash_obj(base, size); + unsigned int j = hash_obj(base, n->size); while (entries[j].base) { if (entries[j].base == base) { @@ -26,7 +23,7 @@ static void *insert_decoration(struct decoration *n, const struct object *base, entries[j].decoration = decoration; return old; } - if (++j >= size) + if (++j >= n->size) j = 0; } entries[j].base = base; @@ -37,8 +34,8 @@ static void *insert_decoration(struct decoration *n, const struct object *base, static void grow_decoration(struct decoration *n) { - int i; - int old_size = n->size; + unsigned int i; + unsigned int old_size = n->size; struct decoration_entry *old_entries = n->entries; n->size = (old_size + 1000) * 3 / 2; @@ -59,9 +56,7 @@ static void grow_decoration(struct decoration *n) void *add_decoration(struct decoration *n, const struct object *obj, void *decoration) { - int nr = n->nr + 1; - - if (nr > n->size * 2 / 3) + if ((n->nr + 1) > n->size * 2 / 3) grow_decoration(n); return insert_decoration(n, obj, decoration); } diff --git a/delta-islands.c b/delta-islands.c index 1c465a6041..3aec43fada 100644 --- a/delta-islands.c +++ b/delta-islands.c @@ -267,7 +267,8 @@ void resolve_tree_islands(struct repository *r, QSORT(todo, nr, tree_depth_compare); if (progress) - progress_state = start_progress(_("Propagating island marks"), nr); + progress_state = start_progress(the_repository, + _("Propagating island marks"), nr); for (i = 0; i < nr; i++) { struct object_entry *ent = todo[i].entry; diff --git a/diagnose.c b/diagnose.c index b11931df86..bd485effea 100644 --- a/diagnose.c +++ b/diagnose.c @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "diagnose.h" #include "compat/disk.h" @@ -12,6 +10,7 @@ #include "object-store-ll.h" #include "packfile.h" #include "parse-options.h" +#include "repository.h" #include "write-or-die.h" struct archive_dir { @@ -179,7 +178,9 @@ static int add_directory_to_archiver(struct strvec *archiver_args, return res; } -int create_diagnostics_archive(struct strbuf *zip_path, enum diagnose_mode mode) +int create_diagnostics_archive(struct repository *r, + struct strbuf *zip_path, + enum diagnose_mode mode) { struct strvec archiver_args = STRVEC_INIT; char **argv_copy = NULL; @@ -218,7 +219,7 @@ int create_diagnostics_archive(struct strbuf *zip_path, enum diagnose_mode mode) strbuf_addstr(&buf, "Collecting diagnostic info\n\n"); get_version_info(&buf, 1); - strbuf_addf(&buf, "Repository root: %s\n", the_repository->worktree); + strbuf_addf(&buf, "Repository root: %s\n", r->worktree); get_disk_info(&buf); write_or_die(stdout_fd, buf.buf, buf.len); strvec_pushf(&archiver_args, @@ -227,7 +228,7 @@ int create_diagnostics_archive(struct strbuf *zip_path, enum diagnose_mode mode) strbuf_reset(&buf); strbuf_addstr(&buf, "--add-virtual-file=packs-local.txt:"); - dir_file_stats(the_repository->objects->odb, &buf); + dir_file_stats(r->objects->odb, &buf); foreach_alt_odb(dir_file_stats, &buf); strvec_push(&archiver_args, buf.buf); @@ -250,13 +251,13 @@ int create_diagnostics_archive(struct strbuf *zip_path, enum diagnose_mode mode) } strvec_pushl(&archiver_args, "--prefix=", - oid_to_hex(the_hash_algo->empty_tree), "--", NULL); + oid_to_hex(r->hash_algo->empty_tree), "--", NULL); /* `write_archive()` modifies the `argv` passed to it. Let it. */ argv_copy = xmemdupz(archiver_args.v, sizeof(char *) * archiver_args.nr); res = write_archive(archiver_args.nr, (const char **)argv_copy, NULL, - the_repository, NULL, 0); + r, NULL, 0); if (res) { error(_("failed to write archive")); goto diagnose_cleanup; diff --git a/diagnose.h b/diagnose.h index f525219ab0..f7b38f49f5 100644 --- a/diagnose.h +++ b/diagnose.h @@ -4,6 +4,7 @@ #include "strbuf.h" struct option; +struct repository; enum diagnose_mode { DIAGNOSE_NONE, @@ -13,6 +14,8 @@ enum diagnose_mode { int option_parse_diagnose(const struct option *opt, const char *arg, int unset); -int create_diagnostics_archive(struct strbuf *zip_path, enum diagnose_mode mode); +int create_diagnostics_archive(struct repository *r, + struct strbuf *zip_path, + enum diagnose_mode mode); #endif /* DIAGNOSE_H */ diff --git a/diff-lib.c b/diff-lib.c index c6d3bc4d37..353b473ed5 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -153,21 +153,8 @@ void run_diff_files(struct rev_info *revs, unsigned int option) struct diff_filepair *pair; unsigned int wt_mode = 0; int num_compare_stages = 0; - size_t path_len; struct stat st; - path_len = ce_namelen(ce); - - dpath = xmalloc(combine_diff_path_size(5, path_len)); - dpath->path = (char *) &(dpath->parent[5]); - - dpath->next = NULL; - memcpy(dpath->path, ce->name, path_len); - dpath->path[path_len] = '\0'; - oidclr(&dpath->oid, the_repository->hash_algo); - memset(&(dpath->parent[0]), 0, - sizeof(struct combine_diff_parent)*5); - changed = check_removed(ce, &st); if (!changed) wt_mode = ce_mode_from_stat(ce, st.st_mode); @@ -178,7 +165,14 @@ void run_diff_files(struct rev_info *revs, unsigned int option) } wt_mode = 0; } - dpath->mode = wt_mode; + + /* + * Allocate space for two parents, which will come from + * index stages #2 and #3, if present. Below we'll fill + * these from (stage - 2). + */ + dpath = combine_diff_path_new(ce->name, ce_namelen(ce), + wt_mode, null_oid(), 2); while (i < entries) { struct cache_entry *nce = istate->cache[i]; @@ -405,16 +399,10 @@ static int show_modified(struct rev_info *revs, if (revs->combine_merges && !cached && (!oideq(oid, &old_entry->oid) || !oideq(&old_entry->oid, &new_entry->oid))) { struct combine_diff_path *p; - int pathlen = ce_namelen(new_entry); - - p = xmalloc(combine_diff_path_size(2, pathlen)); - p->path = (char *) &p->parent[2]; - p->next = NULL; - memcpy(p->path, new_entry->name, pathlen); - p->path[pathlen] = 0; - p->mode = mode; - oidclr(&p->oid, the_repository->hash_algo); - memset(p->parent, 0, 2 * sizeof(struct combine_diff_parent)); + + p = combine_diff_path_new(new_entry->name, + ce_namelen(new_entry), + mode, null_oid(), 2); p->parent[0].status = DIFF_STATUS_MODIFIED; p->parent[0].mode = new_entry->ce_mode; oidcpy(&p->parent[0].oid, &new_entry->oid); @@ -5493,6 +5493,8 @@ static int diff_opt_pickaxe_regex(const struct option *opt, BUG_ON_OPT_NEG(unset); options->pickaxe = arg; options->pickaxe_opts |= DIFF_PICKAXE_KIND_G; + if (arg && !*arg) + return error(_("-G requires a non-empty argument")); return 0; } @@ -5504,6 +5506,8 @@ static int diff_opt_pickaxe_string(const struct option *opt, BUG_ON_OPT_NEG(unset); options->pickaxe = arg; options->pickaxe_opts |= DIFF_PICKAXE_KIND_S; + if (arg && !*arg) + return error(_("-S requires a non-empty argument")); return 0; } @@ -6392,7 +6396,7 @@ static void diff_summary(struct diff_options *opt, struct diff_filepair *p) } struct patch_id_t { - git_hash_ctx *ctx; + struct git_hash_ctx *ctx; int patchlen; }; @@ -6409,13 +6413,13 @@ static int remove_space(char *line, int len) return dst - line; } -void flush_one_hunk(struct object_id *result, git_hash_ctx *ctx) +void flush_one_hunk(struct object_id *result, struct git_hash_ctx *ctx) { unsigned char hash[GIT_MAX_RAWSZ]; unsigned short carry = 0; int i; - the_hash_algo->final_fn(hash, ctx); + git_hash_final(hash, ctx); the_hash_algo->init_fn(ctx); /* 20-byte sum, with carry */ for (i = 0; i < the_hash_algo->rawsz; ++i) { @@ -6434,22 +6438,22 @@ static int patch_id_consume(void *priv, char *line, unsigned long len) return 0; new_len = remove_space(line, len); - the_hash_algo->update_fn(data->ctx, line, new_len); + git_hash_update(data->ctx, line, new_len); data->patchlen += new_len; return 0; } -static void patch_id_add_string(git_hash_ctx *ctx, const char *str) +static void patch_id_add_string(struct git_hash_ctx *ctx, const char *str) { - the_hash_algo->update_fn(ctx, str, strlen(str)); + git_hash_update(ctx, str, strlen(str)); } -static void patch_id_add_mode(git_hash_ctx *ctx, unsigned mode) +static void patch_id_add_mode(struct git_hash_ctx *ctx, unsigned mode) { /* large enough for 2^32 in octal */ char buf[12]; int len = xsnprintf(buf, sizeof(buf), "%06o", mode); - the_hash_algo->update_fn(ctx, buf, len); + git_hash_update(ctx, buf, len); } /* returns 0 upon success, and writes result into oid */ @@ -6457,7 +6461,7 @@ static int diff_get_patch_id(struct diff_options *options, struct object_id *oid { struct diff_queue_struct *q = &diff_queued_diff; int i; - git_hash_ctx ctx; + struct git_hash_ctx ctx; struct patch_id_t data; the_hash_algo->init_fn(&ctx); @@ -6493,9 +6497,9 @@ static int diff_get_patch_id(struct diff_options *options, struct object_id *oid len2 = remove_space(p->two->path, strlen(p->two->path)); patch_id_add_string(&ctx, "diff--git"); patch_id_add_string(&ctx, "a/"); - the_hash_algo->update_fn(&ctx, p->one->path, len1); + git_hash_update(&ctx, p->one->path, len1); patch_id_add_string(&ctx, "b/"); - the_hash_algo->update_fn(&ctx, p->two->path, len2); + git_hash_update(&ctx, p->two->path, len2); if (p->one->mode == 0) { patch_id_add_string(&ctx, "newfilemode"); @@ -6514,24 +6518,24 @@ static int diff_get_patch_id(struct diff_options *options, struct object_id *oid /* don't do anything since we're only populating header info */ } else if (diff_filespec_is_binary(options->repo, p->one) || diff_filespec_is_binary(options->repo, p->two)) { - the_hash_algo->update_fn(&ctx, oid_to_hex(&p->one->oid), + git_hash_update(&ctx, oid_to_hex(&p->one->oid), the_hash_algo->hexsz); - the_hash_algo->update_fn(&ctx, oid_to_hex(&p->two->oid), + git_hash_update(&ctx, oid_to_hex(&p->two->oid), the_hash_algo->hexsz); } else { if (p->one->mode == 0) { patch_id_add_string(&ctx, "---/dev/null"); patch_id_add_string(&ctx, "+++b/"); - the_hash_algo->update_fn(&ctx, p->two->path, len2); + git_hash_update(&ctx, p->two->path, len2); } else if (p->two->mode == 0) { patch_id_add_string(&ctx, "---a/"); - the_hash_algo->update_fn(&ctx, p->one->path, len1); + git_hash_update(&ctx, p->one->path, len1); patch_id_add_string(&ctx, "+++/dev/null"); } else { patch_id_add_string(&ctx, "---a/"); - the_hash_algo->update_fn(&ctx, p->one->path, len1); + git_hash_update(&ctx, p->one->path, len1); patch_id_add_string(&ctx, "+++b/"); - the_hash_algo->update_fn(&ctx, p->two->path, len2); + git_hash_update(&ctx, p->two->path, len2); } if (fill_mmfile(options->repo, &mf1, p->one) < 0 || @@ -7081,7 +7085,7 @@ void diffcore_std(struct diff_options *options) diffcore_order(options->orderfile); if (options->rotate_to) diffcore_rotate(options); - if (!options->found_follow) + if (!options->found_follow && !options->skip_resolving_statuses) /* See try_to_follow_renames() in tree-diff.c */ diff_resolve_rename_copy(); diffcore_apply_filter(options); @@ -7157,16 +7161,19 @@ void compute_diffstat(struct diff_options *options, options->found_changes = !!diffstat->nr; } -void diff_addremove(struct diff_options *options, - int addremove, unsigned mode, - const struct object_id *oid, - int oid_valid, - const char *concatpath, unsigned dirty_submodule) +struct diff_filepair *diff_queue_addremove(struct diff_queue_struct *queue, + struct diff_options *options, + int addremove, unsigned mode, + const struct object_id *oid, + int oid_valid, + const char *concatpath, + unsigned dirty_submodule) { struct diff_filespec *one, *two; + struct diff_filepair *pair; if (S_ISGITLINK(mode) && is_submodule_ignored(concatpath, options)) - return; + return NULL; /* This may look odd, but it is a preparation for * feeding "there are unchanged files which should @@ -7186,7 +7193,7 @@ void diff_addremove(struct diff_options *options, if (options->prefix && strncmp(concatpath, options->prefix, options->prefix_length)) - return; + return NULL; one = alloc_filespec(concatpath); two = alloc_filespec(concatpath); @@ -7198,25 +7205,29 @@ void diff_addremove(struct diff_options *options, two->dirty_submodule = dirty_submodule; } - diff_queue(&diff_queued_diff, one, two); + pair = diff_queue(queue, one, two); if (!options->flags.diff_from_contents) options->flags.has_changes = 1; + + return pair; } -void diff_change(struct diff_options *options, - unsigned old_mode, unsigned new_mode, - const struct object_id *old_oid, - const struct object_id *new_oid, - int old_oid_valid, int new_oid_valid, - const char *concatpath, - unsigned old_dirty_submodule, unsigned new_dirty_submodule) +struct diff_filepair *diff_queue_change(struct diff_queue_struct *queue, + struct diff_options *options, + unsigned old_mode, unsigned new_mode, + const struct object_id *old_oid, + const struct object_id *new_oid, + int old_oid_valid, int new_oid_valid, + const char *concatpath, + unsigned old_dirty_submodule, + unsigned new_dirty_submodule) { struct diff_filespec *one, *two; struct diff_filepair *p; if (S_ISGITLINK(old_mode) && S_ISGITLINK(new_mode) && is_submodule_ignored(concatpath, options)) - return; + return NULL; if (options->flags.reverse_diff) { SWAP(old_mode, new_mode); @@ -7227,7 +7238,7 @@ void diff_change(struct diff_options *options, if (options->prefix && strncmp(concatpath, options->prefix, options->prefix_length)) - return; + return NULL; one = alloc_filespec(concatpath); two = alloc_filespec(concatpath); @@ -7235,19 +7246,42 @@ void diff_change(struct diff_options *options, fill_filespec(two, new_oid, new_oid_valid, new_mode); one->dirty_submodule = old_dirty_submodule; two->dirty_submodule = new_dirty_submodule; - p = diff_queue(&diff_queued_diff, one, two); + p = diff_queue(queue, one, two); if (options->flags.diff_from_contents) - return; + return p; if (options->flags.quick && options->skip_stat_unmatch && !diff_filespec_check_stat_unmatch(options->repo, p)) { diff_free_filespec_data(p->one); diff_free_filespec_data(p->two); - return; + return p; } options->flags.has_changes = 1; + + return p; +} + +void diff_addremove(struct diff_options *options, int addremove, unsigned mode, + const struct object_id *oid, int oid_valid, + const char *concatpath, unsigned dirty_submodule) +{ + diff_queue_addremove(&diff_queued_diff, options, addremove, mode, oid, + oid_valid, concatpath, dirty_submodule); +} + +void diff_change(struct diff_options *options, + unsigned old_mode, unsigned new_mode, + const struct object_id *old_oid, + const struct object_id *new_oid, + int old_oid_valid, int new_oid_valid, + const char *concatpath, + unsigned old_dirty_submodule, unsigned new_dirty_submodule) +{ + diff_queue_change(&diff_queued_diff, options, old_mode, new_mode, + old_oid, new_oid, old_oid_valid, new_oid_valid, + concatpath, old_dirty_submodule, new_dirty_submodule); } struct diff_filepair *diff_unmerge(struct diff_options *options, const char *path) @@ -7386,6 +7420,6 @@ void setup_diff_pager(struct diff_options *opt) * --exit-code" in hooks and other scripts, we do not do so. */ if (!opt->flags.exit_with_status && - check_pager_config("diff") != 0) - setup_pager(); + check_pager_config(the_repository, "diff") != 0) + setup_pager(the_repository); } @@ -333,7 +333,7 @@ struct diff_options { int xdl_opts; int ignore_driver_algorithm; - /* see Documentation/diff-options.txt */ + /* see Documentation/diff-options.adoc */ char **anchors; size_t anchors_nr, anchors_alloc; @@ -353,6 +353,14 @@ struct diff_options { /* to support internal diff recursion by --follow hack*/ int found_follow; + /* + * By default, diffcore_std() resolves the statuses for queued diff file + * pairs by calling diff_resolve_rename_copy(). If status information + * has already been manually set, this option prevents diffcore_std() + * from resetting statuses. + */ + int skip_resolving_statuses; + /* Callback which allows tweaking the options in diff_setup_done(). */ void (*set_default)(struct diff_options *); @@ -462,7 +470,7 @@ const char *diff_line_prefix(struct diff_options *); extern const char mime_boundary_leader[]; struct combine_diff_path *diff_tree_paths( - struct combine_diff_path *p, const struct object_id *oid, + const struct object_id *oid, const struct object_id **parents_oid, int nparent, struct strbuf *base, struct diff_options *opt); void diff_tree_oid(const struct object_id *old_oid, @@ -480,12 +488,20 @@ struct combine_diff_path { char status; unsigned int mode; struct object_id oid; - struct strbuf path; + /* + * This per-parent path is filled only when doing a combined + * diff with revs.combined_all_paths set, and only if the path + * differs from the post-image (e.g., a rename or copy). + * Otherwise it is left NULL. + */ + char *path; } parent[FLEX_ARRAY]; }; -#define combine_diff_path_size(n, l) \ - st_add4(sizeof(struct combine_diff_path), (l), 1, \ - st_mult(sizeof(struct combine_diff_parent), (n))) +struct combine_diff_path *combine_diff_path_new(const char *path, + size_t path_len, + unsigned int mode, + const struct object_id *oid, + size_t num_parents); void show_combined_diff(struct combine_diff_path *elem, int num_parent, struct rev_info *); @@ -500,6 +516,31 @@ void diff_set_default_prefix(struct diff_options *options); int diff_can_quit_early(struct diff_options *); +/* + * Stages changes in the provided diff queue for file additions and deletions. + * If a file pair gets queued, it is returned. + */ +struct diff_filepair *diff_queue_addremove(struct diff_queue_struct *queue, + struct diff_options *, + int addremove, unsigned mode, + const struct object_id *oid, + int oid_valid, const char *fullpath, + unsigned dirty_submodule); + +/* + * Stages changes in the provided diff queue for file modifications. + * If a file pair gets queued, it is returned. + */ +struct diff_filepair *diff_queue_change(struct diff_queue_struct *queue, + struct diff_options *, + unsigned mode1, unsigned mode2, + const struct object_id *old_oid, + const struct object_id *new_oid, + int old_oid_valid, int new_oid_valid, + const char *fullpath, + unsigned dirty_submodule1, + unsigned dirty_submodule2); + void diff_addremove(struct diff_options *, int addremove, unsigned mode, @@ -644,7 +685,7 @@ void run_diff_index(struct rev_info *revs, unsigned int option); int do_diff_cache(const struct object_id *, struct diff_options *); int diff_flush_patch_id(struct diff_options *, struct object_id *, int); -void flush_one_hunk(struct object_id *result, git_hash_ctx *ctx); +void flush_one_hunk(struct object_id *result, struct git_hash_ctx *ctx); int diff_result_code(struct rev_info *); diff --git a/diffcore-rename.c b/diffcore-rename.c index 10bb0321b1..5002e896aa 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -33,7 +33,7 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filepair *p) { /* Lookup by p->ONE->path */ int idx = break_idx ? strintmap_get(break_idx, p->one->path) : -1; - return (idx == -1) ? NULL : &rename_dst[idx]; + return (idx == -1 || idx == rename_dst_nr) ? NULL : &rename_dst[idx]; } /* @@ -1567,6 +1567,7 @@ void diffcore_rename_extended(struct diff_options *options, trace2_region_enter("diff", "inexact renames", options->repo); if (options->show_rename_progress) { progress = start_delayed_progress( + the_repository, _("Performing inexact rename detection"), (uint64_t)num_destinations * (uint64_t)num_sources); } @@ -1668,9 +1669,10 @@ void diffcore_rename_extended(struct diff_options *options, if (DIFF_PAIR_BROKEN(p)) { /* broken delete */ struct diff_rename_dst *dst = locate_rename_dst(p); - if (!dst) - BUG("tracking failed somehow; failed to find associated dst for broken pair"); - if (dst->is_rename) + if (options->single_follow && dst && + strcmp(dst->p->two->path, p->two->path)) + dst = NULL; + if (dst && dst->is_rename) /* counterpart is now rename/copy */ pair_to_free = p; } diff --git a/diffcore.h b/diffcore.h index 2feb325031..9c0a0e7aaf 100644 --- a/diffcore.h +++ b/diffcore.h @@ -107,7 +107,7 @@ struct diff_filepair { struct diff_filespec *one; struct diff_filespec *two; unsigned short int score; - char status; /* M C R A D U etc. (see Documentation/diff-format.txt or DIFF_STATUS_* in diff.h) */ + char status; /* M C R A D U etc. (see Documentation/diff-format.adoc or DIFF_STATUS_* in diff.h) */ unsigned broken_pair : 1; unsigned renamed_pair : 1; unsigned is_unmerged : 1; diff --git a/dir-iterator.c b/dir-iterator.c index de619846f2..857e1d9bda 100644 --- a/dir-iterator.c +++ b/dir-iterator.c @@ -193,9 +193,9 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) if (S_ISDIR(iter->base.st.st_mode) && push_level(iter)) { if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC) - goto error_out; + return ITER_ERROR; if (iter->levels_nr == 0) - goto error_out; + return ITER_ERROR; } /* Loop until we find an entry that we can give back to the caller. */ @@ -211,11 +211,11 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) int ret = next_directory_entry(level->dir, iter->base.path.buf, &de); if (ret < 0) { if (iter->flags & DIR_ITERATOR_PEDANTIC) - goto error_out; + return ITER_ERROR; continue; } else if (ret > 0) { if (pop_level(iter) == 0) - return dir_iterator_abort(dir_iterator); + return ITER_DONE; continue; } @@ -223,7 +223,7 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) } else { if (level->entries_idx >= level->entries.nr) { if (pop_level(iter) == 0) - return dir_iterator_abort(dir_iterator); + return ITER_DONE; continue; } @@ -232,22 +232,21 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) if (prepare_next_entry_data(iter, name)) { if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC) - goto error_out; + return ITER_ERROR; continue; } return ITER_OK; } - -error_out: - dir_iterator_abort(dir_iterator); - return ITER_ERROR; } -int dir_iterator_abort(struct dir_iterator *dir_iterator) +void dir_iterator_free(struct dir_iterator *dir_iterator) { struct dir_iterator_int *iter = (struct dir_iterator_int *)dir_iterator; + if (!iter) + return; + for (; iter->levels_nr; iter->levels_nr--) { struct dir_iterator_level *level = &iter->levels[iter->levels_nr - 1]; @@ -266,7 +265,6 @@ int dir_iterator_abort(struct dir_iterator *dir_iterator) free(iter->levels); strbuf_release(&iter->base.path); free(iter); - return ITER_DONE; } struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags) @@ -301,7 +299,7 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags) return dir_iterator; error_out: - dir_iterator_abort(dir_iterator); + dir_iterator_free(dir_iterator); errno = saved_errno; return NULL; } diff --git a/dir-iterator.h b/dir-iterator.h index 6d438809b6..ccd6a19734 100644 --- a/dir-iterator.h +++ b/dir-iterator.h @@ -28,7 +28,7 @@ * * while ((ok = dir_iterator_advance(iter)) == ITER_OK) { * if (want_to_stop_iteration()) { - * ok = dir_iterator_abort(iter); + * ok = ITER_DONE; * break; * } * @@ -39,6 +39,7 @@ * * if (ok != ITER_DONE) * handle_error(); + * dir_iterator_free(iter); * * Callers are allowed to modify iter->path while they are working, * but they must restore it to its original contents before calling @@ -107,11 +108,7 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags); */ int dir_iterator_advance(struct dir_iterator *iterator); -/* - * End the iteration before it has been exhausted. Free the - * dir_iterator and any associated resources and return ITER_DONE. On - * error, free the dir_iterator and return ITER_ERROR. - */ -int dir_iterator_abort(struct dir_iterator *iterator); +/* Free the dir_iterator and any associated resources. */ +void dir_iterator_free(struct dir_iterator *iterator); #endif @@ -1093,10 +1093,6 @@ static void invalidate_directory(struct untracked_cache *uc, dir->dirs[i]->recurse = 0; } -static int add_patterns_from_buffer(char *buf, size_t size, - const char *base, int baselen, - struct pattern_list *pl); - /* Flags for add_patterns() */ #define PATTERN_NOFOLLOW (1<<0) @@ -1186,9 +1182,9 @@ static int add_patterns(const char *fname, const char *base, int baselen, return 0; } -static int add_patterns_from_buffer(char *buf, size_t size, - const char *base, int baselen, - struct pattern_list *pl) +int add_patterns_from_buffer(char *buf, size_t size, + const char *base, int baselen, + struct pattern_list *pl) { char *orig = buf; int i, lineno = 1; @@ -3455,7 +3451,7 @@ void setup_standard_excludes(struct dir_struct *dir) char *get_sparse_checkout_filename(void) { - return git_pathdup("info/sparse-checkout"); + return repo_git_path(the_repository, "info/sparse-checkout"); } int get_sparse_checkout_patterns(struct pattern_list *pl) @@ -43,7 +43,6 @@ struct repository; * */ -struct repository; struct dir_entry { unsigned int len; @@ -467,6 +466,9 @@ void add_patterns_from_file(struct dir_struct *, const char *fname); int add_patterns_from_blob_to_list(struct object_id *oid, const char *base, int baselen, struct pattern_list *pl); +int add_patterns_from_buffer(char *buf, size_t size, + const char *base, int baselen, + struct pattern_list *pl); void parse_path_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen); void add_pattern(const char *string, const char *base, int baselen, struct pattern_list *pl, int srcpos); @@ -142,10 +142,8 @@ int strbuf_edit_interactively(struct repository *r, struct strbuf sb = STRBUF_INIT; int fd, res = 0; - if (!is_absolute_path(path)) { - strbuf_repo_git_path(&sb, r, "%s", path); - path = sb.buf; - } + if (!is_absolute_path(path)) + path = repo_git_path_append(r, &sb, "%s", path); fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) @@ -188,7 +188,9 @@ int finish_delayed_checkout(struct checkout *state, int show_progress) dco->state = CE_RETRY; if (show_progress) - progress = start_delayed_progress(_("Filtering content"), dco->paths.nr); + progress = start_delayed_progress(the_repository, + _("Filtering content"), + dco->paths.nr); while (dco->filters.nr > 0) { for_each_string_list_item(filter, &dco->filters) { struct string_list available_paths = STRING_LIST_INIT_DUP; diff --git a/environment.c b/environment.c index 8389a27270..9e4c7781be 100644 --- a/environment.c +++ b/environment.c @@ -16,6 +16,7 @@ #include "convert.h" #include "environment.h" #include "gettext.h" +#include "git-zlib.h" #include "repository.h" #include "config.h" #include "refs.h" @@ -42,7 +43,6 @@ char *git_log_output_encoding; char *apply_default_whitespace; char *apply_default_ignorewhitespace; char *git_attributes_file; -char *git_hooks_path; int zlib_compression_level = Z_BEST_SPEED; int pack_compression_level = Z_DEFAULT_COMPRESSION; int fsync_object_files = -1; @@ -207,32 +207,6 @@ const char *get_commit_output_encoding(void) return git_commit_encoding ? git_commit_encoding : "UTF-8"; } -static int the_shared_repository = PERM_UMASK; -static int need_shared_repository_from_config = 1; - -void set_shared_repository(int value) -{ - the_shared_repository = value; - need_shared_repository_from_config = 0; -} - -int get_shared_repository(void) -{ - if (need_shared_repository_from_config) { - const char *var = "core.sharedrepository"; - const char *value; - if (!git_config_get_value(var, &value)) - the_shared_repository = git_config_perm(var, value); - need_shared_repository_from_config = 0; - } - return the_shared_repository; -} - -void reset_shared_repository(void) -{ - need_shared_repository_from_config = 1; -} - int use_optional_locks(void) { return git_env_bool(GIT_OPTIONAL_LOCKS_ENVIRONMENT, 1); diff --git a/environment.h b/environment.h index 2f43340f0b..45e690f203 100644 --- a/environment.h +++ b/environment.h @@ -134,16 +134,6 @@ void setup_git_env(const char *git_dir); */ int have_git_dir(void); -/* - * Accessors for the core.sharedrepository config which lazy-load the value - * from the config (if not already set). The "reset" function can be - * used to unset "set" or cached value, meaning that the value will be loaded - * fresh from the config file on the next call to get_shared_repository(). - */ -void set_shared_repository(int value); -int get_shared_repository(void); -void reset_shared_repository(void); - extern int is_bare_repository_cfg; int is_bare_repository(void); extern char *git_work_tree_cfg; @@ -160,7 +150,6 @@ extern int warn_on_object_refname_ambiguity; extern char *apply_default_whitespace; extern char *apply_default_ignorewhitespace; extern char *git_attributes_file; -extern char *git_hooks_path; extern int zlib_compression_level; extern int pack_compression_level; extern size_t packed_git_window_size; diff --git a/fetch-pack.c b/fetch-pack.c index 3a227721ed..1ed5e11dd5 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -1036,7 +1036,9 @@ static int get_pack(struct fetch_pack_args *args, die(_("fetch-pack: unable to fork off %s"), cmd_name); if (do_keep && (pack_lockfiles || fsck_objects)) { int is_well_formed; - char *pack_lockfile = index_pack_lockfile(cmd.out, &is_well_formed); + char *pack_lockfile = index_pack_lockfile(the_repository, + cmd.out, + &is_well_formed); if (!is_well_formed) die(_("fetch-pack: invalid index-pack output")); @@ -1867,7 +1869,7 @@ int fetch_pack_fsck_config(const char *var, const char *value, char *path ; if (git_config_pathname(&path, var, value)) - return 0; + return -1; strbuf_addf(msg_types, "%cskiplist=%s", msg_types->len ? ',' : '=', path); free(path); @@ -1353,7 +1353,7 @@ int git_fsck_config(const char *var, const char *value, struct strbuf sb = STRBUF_INIT; if (git_config_pathname(&path, var, value)) - return 1; + return -1; strbuf_addf(&sb, "skiplist=%s", path); free(path); fsck_set_msg_types(options, sb.buf); @@ -15,7 +15,7 @@ enum fsck_msg_type { }; /* - * Documentation/fsck-msgids.txt documents these; when + * Documentation/fsck-msgids.adoc documents these; when * modifying this list in any way, make sure to keep the * two in sync. */ @@ -30,6 +30,8 @@ enum fsck_msg_type { FUNC(BAD_EMAIL, ERROR) \ FUNC(BAD_NAME, ERROR) \ FUNC(BAD_OBJECT_SHA1, ERROR) \ + FUNC(BAD_PACKED_REF_ENTRY, ERROR) \ + FUNC(BAD_PACKED_REF_HEADER, ERROR) \ FUNC(BAD_PARENT_SHA1, ERROR) \ FUNC(BAD_REF_CONTENT, ERROR) \ FUNC(BAD_REF_FILETYPE, ERROR) \ @@ -53,6 +55,8 @@ enum fsck_msg_type { FUNC(MISSING_TYPE, ERROR) \ FUNC(MISSING_TYPE_ENTRY, ERROR) \ FUNC(MULTIPLE_AUTHORS, ERROR) \ + FUNC(PACKED_REF_ENTRY_NOT_TERMINATED, ERROR) \ + FUNC(PACKED_REF_UNSORTED, ERROR) \ FUNC(TREE_NOT_SORTED, ERROR) \ FUNC(UNKNOWN_TYPE, ERROR) \ FUNC(ZERO_PADDED_DATE, ERROR) \ diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh index b923a5aab8..0ed39c4c5d 100755 --- a/generate-cmdlist.sh +++ b/generate-cmdlist.sh @@ -76,7 +76,7 @@ print_command_list () { break ;; esac - done <"$1/Documentation/$cmd.txt" + done <"$1/Documentation/$cmd.adoc" printf '\t{ "%s", N_("%s"), 0' "$cmd" "$synopsis" printf " | CAT_%s" $rest diff --git a/generate-configlist.sh b/generate-configlist.sh index 579422619c..dffdaada8b 100755 --- a/generate-configlist.sh +++ b/generate-configlist.sh @@ -13,7 +13,7 @@ print_config_list () { cat <<EOF static const char *config_name_list[] = { EOF - grep -h '^[a-zA-Z].*\..*::$' "$SOURCE_DIR"/Documentation/*config.txt "$SOURCE_DIR"/Documentation/config/*.txt | + grep -h '^[a-zA-Z].*\..*::$' "$SOURCE_DIR"/Documentation/*config.adoc "$SOURCE_DIR"/Documentation/config/*.adoc | sed '/deprecated/d; s/::$//; s/, */\n/g' | sort | sed 's/^.*$/ "&",/' diff --git a/generate-hooklist.sh b/generate-hooklist.sh index e22068c2fa..e0cdf26944 100755 --- a/generate-hooklist.sh +++ b/generate-hooklist.sh @@ -22,7 +22,7 @@ EOF sed -n \ -e '/^~~~~*$/ {x; s/^.*$/ "&",/; p;}' \ -e 'x' \ - <"$SOURCE_DIR"/Documentation/githooks.txt | + <"$SOURCE_DIR"/Documentation/githooks.adoc | LC_ALL=C sort cat <<EOF diff --git a/git-compat-util.h b/git-compat-util.h index c4f96dcc7b..cf733b38ac 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -701,6 +701,8 @@ int error_errno(const char *err, ...) __attribute__((format (printf, 1, 2))); void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); void warning_errno(const char *err, ...) __attribute__((format (printf, 1, 2))); +void show_usage_if_asked(int ac, const char **av, const char *err); + #ifndef NO_OPENSSL #ifdef APPLE_COMMON_CRYPTO #include "compat/apple-common-crypto.h" @@ -1537,18 +1539,6 @@ int cmd_main(int, const char **); int common_exit(const char *file, int line, int code); #define exit(code) exit(common_exit(__FILE__, __LINE__, (code))) -#define z_const -#include <zlib.h> - -#if ZLIB_VERNUM < 0x1290 -/* - * This is uncompress2, which is only available in zlib >= 1.2.9 - * (released as of early 2017). See compat/zlib-uncompress2.c. - */ -int uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source, - uLong *sourceLen); -#endif - /* * This include must come after system headers, since it introduces macros that * replace system names. diff --git a/git-gui/Makefile b/git-gui/Makefile index 667c39ed56..6c5a12bc32 100644 --- a/git-gui/Makefile +++ b/git-gui/Makefile @@ -1,3 +1,4 @@ +# The default target of this Makefile is... all:: # Define V=1 to have a more verbose compile. diff --git a/git-gui/po/glossary/Makefile b/git-gui/po/glossary/Makefile index 749aa2e7ec..e656b0d2b0 100644 --- a/git-gui/po/glossary/Makefile +++ b/git-gui/po/glossary/Makefile @@ -1,3 +1,6 @@ +# The default target of this Makefile is... +update-po:: + PO_TEMPLATE = git-gui-glossary.pot ALL_POFILES = $(wildcard *.po) diff --git a/git-instaweb.sh b/git-instaweb.sh index 5ad50160bb..7b44f70789 100755 --- a/git-instaweb.sh +++ b/git-instaweb.sh @@ -694,9 +694,9 @@ class GitWebRequestHandler(CGIHTTPRequestHandler): return result -bind = "127.0.0.1" +bind = "0.0.0.0" if "$local" == "true": - bind = "0.0.0.0" + bind = "127.0.0.1" # Set our http root directory # This is a work around for a missing directory argument in older Python versions diff --git a/git-submodule.sh b/git-submodule.sh index 03c5a220a2..2999b31fad 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -40,11 +40,11 @@ init= require_init= files= remote= -nofetch= +no_fetch= rebase= merge= checkout= -custom_name= +name= depth= progress= dissociate= @@ -52,11 +52,10 @@ single_branch= jobs= recommend_shallow= filter= - -isnumber() -{ - n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1" -} +all= +default= +summary_limit= +for_status= # # Add a new submodule to the working tree, .gitmodules and the index @@ -68,31 +67,33 @@ isnumber() cmd_add() { # parse $args after "submodule ... add". - reference_path= while test $# -ne 0 do case "$1" in -b | --branch) case "$2" in '') usage ;; esac - branch=$2 + branch="--branch=$2" shift ;; + -b* | --branch=*) + branch="$1" + ;; -f | --force) force=$1 ;; -q|--quiet) - quiet=1 + quiet=$1 ;; --progress) - progress=1 + progress=$1 ;; --reference) case "$2" in '') usage ;; esac - reference_path=$2 + reference="--reference=$2" shift ;; --reference=*) - reference_path="${1#--reference=}" + reference="$1" ;; --ref-format) case "$2" in '') usage ;; esac @@ -103,20 +104,23 @@ cmd_add() ref_format="$1" ;; --dissociate) - dissociate=1 + dissociate=$1 ;; --name) case "$2" in '') usage ;; esac - custom_name=$2 + name="--name=$2" shift ;; + --name=*) + name="$1" + ;; --depth) case "$2" in '') usage ;; esac depth="--depth=$2" shift ;; --depth=*) - depth=$1 + depth="$1" ;; --) shift @@ -138,14 +142,14 @@ cmd_add() fi git ${wt_prefix:+-C "$wt_prefix"} submodule--helper add \ - ${quiet:+--quiet} \ - ${force:+--force} \ - ${progress:+"--progress"} \ - ${branch:+--branch "$branch"} \ - ${reference_path:+--reference "$reference_path"} \ + $quiet \ + $force \ + $progress \ + ${branch:+"$branch"} \ + ${reference:+"$reference"} \ ${ref_format:+"$ref_format"} \ - ${dissociate:+--dissociate} \ - ${custom_name:+--name "$custom_name"} \ + $dissociate \ + ${name:+"$name"} \ ${depth:+"$depth"} \ -- \ "$@" @@ -164,10 +168,10 @@ cmd_foreach() do case "$1" in -q|--quiet) - quiet=1 + quiet=$1 ;; --recursive) - recursive=1 + recursive=$1 ;; -*) usage @@ -180,8 +184,8 @@ cmd_foreach() done git ${wt_prefix:+-C "$wt_prefix"} submodule--helper foreach \ - ${quiet:+--quiet} \ - ${recursive:+--recursive} \ + $quiet \ + $recursive \ -- \ "$@" } @@ -198,7 +202,7 @@ cmd_init() do case "$1" in -q|--quiet) - quiet=1 + quiet=$1 ;; --) shift @@ -215,7 +219,7 @@ cmd_init() done git ${wt_prefix:+-C "$wt_prefix"} submodule--helper init \ - ${quiet:+--quiet} \ + $quiet \ -- \ "$@" } @@ -226,7 +230,6 @@ cmd_init() cmd_deinit() { # parse $args after "submodule ... deinit". - deinit_all= while test $# -ne 0 do case "$1" in @@ -234,10 +237,10 @@ cmd_deinit() force=$1 ;; -q|--quiet) - quiet=1 + quiet=$1 ;; --all) - deinit_all=t + all=$1 ;; --) shift @@ -254,9 +257,9 @@ cmd_deinit() done git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit \ - ${quiet:+--quiet} \ - ${force:+--force} \ - ${deinit_all:+--all} \ + $quiet \ + $force \ + $all \ -- \ "$@" } @@ -273,31 +276,31 @@ cmd_update() do case "$1" in -q|--quiet) - quiet=1 + quiet=$1 ;; -v|--verbose) - quiet=0 + quiet= ;; --progress) - progress=1 + progress=$1 ;; -i|--init) - init=1 + init=$1 ;; --require-init) - require_init=1 + require_init=$1 ;; --remote) - remote=1 + remote=$1 ;; -N|--no-fetch) - nofetch=1 + no_fetch=$1 ;; -f|--force) force=$1 ;; -r|--rebase) - rebase=1 + rebase=$1 ;; --ref-format) case "$2" in '') usage ;; esac @@ -316,22 +319,19 @@ cmd_update() reference="$1" ;; --dissociate) - dissociate=1 + dissociate=$1 ;; -m|--merge) - merge=1 + merge=$1 ;; --recursive) - recursive=1 + recursive=$1 ;; --checkout) - checkout=1 - ;; - --recommend-shallow) - recommend_shallow="--recommend-shallow" + checkout=$1 ;; - --no-recommend-shallow) - recommend_shallow="--no-recommend-shallow" + --recommend-shallow|--no-recommend-shallow) + recommend_shallow=$1 ;; --depth) case "$2" in '') usage ;; esac @@ -339,21 +339,18 @@ cmd_update() shift ;; --depth=*) - depth=$1 + depth="$1" ;; -j|--jobs) case "$2" in '') usage ;; esac jobs="--jobs=$2" shift ;; - --jobs=*) - jobs=$1 + -j*|--jobs=*) + jobs="$1" ;; - --single-branch) - single_branch="--single-branch" - ;; - --no-single-branch) - single_branch="--no-single-branch" + --single-branch|--no-single-branch) + single_branch=$1 ;; --filter) case "$2" in '') usage ;; esac @@ -378,22 +375,21 @@ cmd_update() done git ${wt_prefix:+-C "$wt_prefix"} submodule--helper update \ - ${quiet:+--quiet} \ - ${force:+--force} \ - ${progress:+"--progress"} \ - ${remote:+--remote} \ - ${recursive:+--recursive} \ - ${init:+--init} \ - ${nofetch:+--no-fetch} \ - ${rebase:+--rebase} \ - ${merge:+--merge} \ - ${checkout:+--checkout} \ + $quiet \ + $force \ + $progress \ + $remote \ + $recursive \ + $init \ + $no_fetch \ + $rebase \ + $merge \ + $checkout \ ${ref_format:+"$ref_format"} \ ${reference:+"$reference"} \ - ${dissociate:+"--dissociate"} \ + $dissociate \ ${depth:+"$depth"} \ - ${require_init:+--require-init} \ - ${dissociate:+"--dissociate"} \ + $require_init \ $single_branch \ $recommend_shallow \ $jobs \ @@ -408,9 +404,7 @@ cmd_update() # $@ = requested path # cmd_set_branch() { - default= - branch= - + # parse $args after "submodule ... set-branch". while test $# -ne 0 do case "$1" in @@ -418,13 +412,16 @@ cmd_set_branch() { # we don't do anything with this but we need to accept it ;; -d|--default) - default=1 + default=$1 ;; -b|--branch) case "$2" in '') usage ;; esac - branch=$2 + branch="--branch=$2" shift ;; + -b*|--branch=*) + branch="$1" + ;; --) shift break @@ -440,9 +437,9 @@ cmd_set_branch() { done git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-branch \ - ${quiet:+--quiet} \ - ${branch:+--branch "$branch"} \ - ${default:+--default} \ + $quiet \ + ${branch:+"$branch"} \ + $default \ -- \ "$@" } @@ -453,11 +450,12 @@ cmd_set_branch() { # $@ = requested path, requested url # cmd_set_url() { + # parse $args after "submodule ... set-url". while test $# -ne 0 do case "$1" in -q|--quiet) - quiet=1 + quiet=$1 ;; --) shift @@ -474,7 +472,7 @@ cmd_set_url() { done git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-url \ - ${quiet:+--quiet} \ + $quiet \ -- \ "$@" } @@ -488,31 +486,26 @@ cmd_set_url() { # $@ = [commit (default 'HEAD'),] requested paths (default all) # cmd_summary() { - summary_limit=-1 - for_status= - diff_cmd=diff-index - # parse $args after "submodule ... summary". while test $# -ne 0 do case "$1" in --cached) - cached=1 + cached=$1 ;; --files) - files="$1" + files=$1 ;; --for-status) - for_status="$1" + for_status=$1 ;; -n|--summary-limit) - summary_limit="$2" - isnumber "$summary_limit" || usage + case "$2" in '') usage ;; esac + summary_limit="--summary-limit=$2" shift ;; - --summary-limit=*) - summary_limit="${1#--summary-limit=}" - isnumber "$summary_limit" || usage + -n*|--summary-limit=*) + summary_limit="$1" ;; --) shift @@ -529,10 +522,10 @@ cmd_summary() { done git ${wt_prefix:+-C "$wt_prefix"} submodule--helper summary \ - ${files:+--files} \ - ${cached:+--cached} \ - ${for_status:+--for-status} \ - ${summary_limit:+-n $summary_limit} \ + $files \ + $cached \ + $for_status \ + ${summary_limit:+"$summary_limit"} \ -- \ "$@" } @@ -553,13 +546,13 @@ cmd_status() do case "$1" in -q|--quiet) - quiet=1 + quiet=$1 ;; --cached) - cached=1 + cached=$1 ;; --recursive) - recursive=1 + recursive=$1 ;; --) shift @@ -576,9 +569,9 @@ cmd_status() done git ${wt_prefix:+-C "$wt_prefix"} submodule--helper status \ - ${quiet:+--quiet} \ - ${cached:+--cached} \ - ${recursive:+--recursive} \ + $quiet \ + $cached \ + $recursive \ -- \ "$@" } @@ -590,15 +583,16 @@ cmd_status() # cmd_sync() { + # parse $args after "submodule ... sync". while test $# -ne 0 do case "$1" in -q|--quiet) - quiet=1 + quiet=$1 shift ;; --recursive) - recursive=1 + recursive=$1 shift ;; --) @@ -615,8 +609,8 @@ cmd_sync() done git ${wt_prefix:+-C "$wt_prefix"} submodule--helper sync \ - ${quiet:+--quiet} \ - ${recursive:+--recursive} \ + $quiet \ + $recursive \ -- \ "$@" } @@ -639,10 +633,10 @@ do command=$1 ;; -q|--quiet) - quiet=1 + quiet=$1 ;; --cached) - cached=1 + cached=$1 ;; --) break diff --git a/git-zlib.c b/git-zlib.c index d43bbeb6da..651dd9e07c 100644 --- a/git-zlib.c +++ b/git-zlib.c @@ -59,7 +59,8 @@ static void zlib_post_call(git_zstream *s) s->total_out = s->z.total_out; s->total_in = s->z.total_in; - s->next_in = s->z.next_in; + /* zlib-ng marks `next_in` as `const`, so we have to cast it away. */ + s->next_in = (unsigned char *) s->z.next_in; s->next_out = s->z.next_out; s->avail_in -= bytes_consumed; s->avail_out -= bytes_produced; @@ -147,10 +148,6 @@ int git_inflate(git_zstream *strm, int flush) return status; } -#if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200 -#define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11) -#endif - unsigned long git_deflate_bound(git_zstream *strm, unsigned long size) { return deflateBound(&strm->z, size); diff --git a/git-zlib.h b/git-zlib.h index d8a670aff9..1e8d9aabcb 100644 --- a/git-zlib.h +++ b/git-zlib.h @@ -1,6 +1,8 @@ #ifndef GIT_ZLIB_H #define GIT_ZLIB_H +#include "compat/zlib-compat.h" + typedef struct git_zstream { z_stream z; unsigned long avail_in; @@ -125,7 +125,7 @@ static void commit_pager_choice(void) setenv("GIT_PAGER", "cat", 1); break; case 1: - setup_pager(); + setup_pager(the_repository); break; default: break; @@ -136,7 +136,7 @@ void setup_auto_pager(const char *cmd, int def) { if (use_pager != -1 || pager_in_use()) return; - use_pager = check_pager_config(cmd); + use_pager = check_pager_config(the_repository, cmd); if (use_pager == -1) use_pager = def; commit_pager_choice(); @@ -462,12 +462,12 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv, struct precompose_argv_prefix(argc, argv, NULL); if (use_pager == -1 && run_setup && !(p->option & DELAY_PAGER_CONFIG)) - use_pager = check_pager_config(p->cmd); + use_pager = check_pager_config(the_repository, p->cmd); if (use_pager == -1 && p->option & USE_PAGER) use_pager = 1; if (run_setup && startup_info->have_repository) /* get_git_dir() may set up repo, avoid that */ - trace_repo_setup(); + trace_repo_setup(the_repository); commit_pager_choice(); if (!help && p->option & NEED_WORK_TREE) @@ -506,6 +506,7 @@ static struct cmd_struct commands[] = { { "annotate", cmd_annotate, RUN_SETUP }, { "apply", cmd_apply, RUN_SETUP_GENTLY }, { "archive", cmd_archive, RUN_SETUP_GENTLY }, + { "backfill", cmd_backfill, RUN_SETUP }, { "bisect", cmd_bisect, RUN_SETUP }, { "blame", cmd_blame, RUN_SETUP }, { "branch", cmd_branch, RUN_SETUP | DELAY_PAGER_CONFIG }, @@ -540,6 +541,7 @@ static struct cmd_struct commands[] = { { "diff", cmd_diff, NO_PARSEOPT }, { "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "diff-index", cmd_diff_index, RUN_SETUP | NO_PARSEOPT }, + { "diff-pairs", cmd_diff_pairs, RUN_SETUP | NO_PARSEOPT }, { "diff-tree", cmd_diff_tree, RUN_SETUP | NO_PARSEOPT }, { "difftool", cmd_difftool, RUN_SETUP_GENTLY }, { "fast-export", cmd_fast_export, RUN_SETUP }, @@ -587,7 +589,9 @@ static struct cmd_struct commands[] = { { "name-rev", cmd_name_rev, RUN_SETUP }, { "notes", cmd_notes, RUN_SETUP }, { "pack-objects", cmd_pack_objects, RUN_SETUP }, +#ifndef WITH_BREAKING_CHANGES { "pack-redundant", cmd_pack_redundant, RUN_SETUP | NO_PARSEOPT }, +#endif { "pack-refs", cmd_pack_refs, RUN_SETUP }, { "patch-id", cmd_patch_id, RUN_SETUP_GENTLY | NO_PARSEOPT }, { "pickaxe", cmd_blame, RUN_SETUP }, @@ -750,7 +754,7 @@ static void execv_dashed_external(const char **argv) int status; if (use_pager == -1 && !is_builtin(argv[0])) - use_pager = check_pager_config(argv[0]); + use_pager = check_pager_config(the_repository, argv[0]); commit_pager_choice(); strvec_pushf(&cmd.args, "git-%s", argv[0]); diff --git a/gitk-git/Makefile b/gitk-git/Makefile index e1f0aff4a1..3a3c56c318 100644 --- a/gitk-git/Makefile +++ b/gitk-git/Makefile @@ -8,6 +8,7 @@ gitk_libdir ?= $(sharedir)/gitk/lib msgsdir ?= $(gitk_libdir)/msgs msgsdir_SQ = $(subst ','\'',$(msgsdir)) +SHELL_PATH ?= /bin/sh TCL_PATH ?= tclsh TCLTK_PATH ?= wish INSTALL ?= install @@ -64,9 +65,7 @@ clean:: gitk-wish: gitk GIT-TCLTK-VARS $(QUIET_GEN)$(RM) $@ $@+ && \ - sed -e '1,3s|^exec .* "$$0"|exec $(subst |,'\|',$(TCLTK_PATH_SQ)) "$$0"|' <gitk >$@+ && \ - chmod +x $@+ && \ - mv -f $@+ $@ + $(SHELL_PATH) ./generate-tcl.sh "$(TCLTK_PATH_SQ)" "$<" "$@" $(PO_TEMPLATE): gitk $(XGETTEXT) -kmc -LTcl -o $@ gitk diff --git a/gitk-git/generate-tcl.sh b/gitk-git/generate-tcl.sh new file mode 100755 index 0000000000..46bba6d246 --- /dev/null +++ b/gitk-git/generate-tcl.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e + +WISH=$(echo "$1" | sed 's/|/\\|/g') +INPUT="$2" +OUTPUT="$3" + +sed -e "1,3s|^exec .* \"\$0\"|exec $WISH \"\$0\"|" "$INPUT" >"$OUTPUT"+ +chmod a+x "$OUTPUT"+ +mv "$OUTPUT"+ "$OUTPUT" diff --git a/gitk-git/gitk b/gitk-git/gitk index 47a7c1d29c..bc9efa1856 100755 --- a/gitk-git/gitk +++ b/gitk-git/gitk @@ -9,6 +9,141 @@ exec wish "$0" -- "$@" package require Tk +###################################################################### +## +## Enabling platform-specific code paths + +proc is_MacOSX {} { + if {[tk windowingsystem] eq {aqua}} { + return 1 + } + return 0 +} + +proc is_Windows {} { + if {$::tcl_platform(platform) eq {windows}} { + return 1 + } + return 0 +} + +set _iscygwin {} +proc is_Cygwin {} { + global _iscygwin + if {$_iscygwin eq {}} { + if {[string match "CYGWIN_*" $::tcl_platform(os)]} { + set _iscygwin 1 + } else { + set _iscygwin 0 + } + } + return $_iscygwin +} + +###################################################################### +## +## PATH lookup + +set _search_path {} +proc _which {what args} { + global env _search_exe _search_path + + if {$_search_path eq {}} { + if {[is_Cygwin] && [regexp {^(/|\.:)} $env(PATH)]} { + set _search_path [split [exec cygpath \ + --windows \ + --path \ + --absolute \ + $env(PATH)] {;}] + set _search_exe .exe + } elseif {[is_Windows]} { + set gitguidir [file dirname [info script]] + regsub -all ";" $gitguidir "\\;" gitguidir + set env(PATH) "$gitguidir;$env(PATH)" + set _search_path [split $env(PATH) {;}] + # Skip empty `PATH` elements + set _search_path [lsearch -all -inline -not -exact \ + $_search_path ""] + set _search_exe .exe + } else { + set _search_path [split $env(PATH) :] + set _search_exe {} + } + } + + if {[is_Windows] && [lsearch -exact $args -script] >= 0} { + set suffix {} + } else { + set suffix $_search_exe + } + + foreach p $_search_path { + set p [file join $p $what$suffix] + if {[file exists $p]} { + return [file normalize $p] + } + } + return {} +} + +proc sanitize_command_line {command_line from_index} { + set i $from_index + while {$i < [llength $command_line]} { + set cmd [lindex $command_line $i] + if {[file pathtype $cmd] ne "absolute"} { + set fullpath [_which $cmd] + if {$fullpath eq ""} { + throw {NOT-FOUND} "$cmd not found in PATH" + } + lset command_line $i $fullpath + } + + # handle piped commands, e.g. `exec A | B` + for {incr i} {$i < [llength $command_line]} {incr i} { + if {[lindex $command_line $i] eq "|"} { + incr i + break + } + } + } + return $command_line +} + +# Override `exec` to avoid unsafe PATH lookup + +rename exec real_exec + +proc exec {args} { + # skip options + for {set i 0} {$i < [llength $args]} {incr i} { + set arg [lindex $args $i] + if {$arg eq "--"} { + incr i + break + } + if {[string range $arg 0 0] ne "-"} { + break + } + } + set args [sanitize_command_line $args $i] + uplevel 1 real_exec $args +} + +# Override `open` to avoid unsafe PATH lookup + +rename open real_open + +proc open {args} { + set arg0 [lindex $args 0] + if {[string range $arg0 0 0] eq "|"} { + set command_line [string trim [string range $arg0 1 end]] + lset args 0 "| [sanitize_command_line $command_line 0]" + } + uplevel 1 real_open $args +} + +# End of safe PATH lookup stuff + proc hasworktree {} { return [expr {[exec git rev-parse --is-bare-repository] == "false" && [exec git rev-parse --is-inside-git-dir] == "false"}] @@ -2103,7 +2238,7 @@ proc makewindow {} { global headctxmenu progresscanv progressitem progresscoords statusw global fprogitem fprogcoord lastprogupdate progupdatepending global rprogitem rprogcoord rownumsel numcommits - global have_tk85 use_ttk NS + global have_tk85 have_tk86 use_ttk NS global git_version global worddiff @@ -2601,8 +2736,13 @@ proc makewindow {} { bind . <Key-Down> "selnextline 1" bind . <Shift-Key-Up> "dofind -1 0" bind . <Shift-Key-Down> "dofind 1 0" - bindkey <Key-Right> "goforw" - bindkey <Key-Left> "goback" + if {$have_tk86} { + bindkey <<NextChar>> "goforw" + bindkey <<PrevChar>> "goback" + } else { + bindkey <Key-Right> "goforw" + bindkey <Key-Left> "goback" + } bind . <Key-Prior> "selnextpage -1" bind . <Key-Next> "selnextpage 1" bind . <$M1B-Home> "allcanvs yview moveto 0.0" @@ -7720,7 +7860,7 @@ proc gettreeline {gtf id} { if {[string index $fname 0] eq "\""} { set fname [lindex $fname 0] } - set fname [encoding convertfrom $fname] + set fname [encoding convertfrom utf-8 $fname] lappend treefilelist($id) $fname } if {![eof $gtf]} { @@ -7982,7 +8122,7 @@ proc gettreediffline {gdtf ids} { if {[string index $file 0] eq "\""} { set file [lindex $file 0] } - set file [encoding convertfrom $file] + set file [encoding convertfrom utf-8 $file] if {$file ne [lindex $treediff end]} { lappend treediff $file lappend sublist $file @@ -8127,7 +8267,7 @@ proc makediffhdr {fname ids} { global ctext curdiffstart treediffs diffencoding global ctext_file_names jump_to_here targetline diffline - set fname [encoding convertfrom $fname] + set fname [encoding convertfrom utf-8 $fname] set diffencoding [get_path_encoding $fname] set i [lsearch -exact $treediffs($ids) $fname] if {$i >= 0} { @@ -8189,7 +8329,7 @@ proc parseblobdiffline {ids line} { if {![string compare -length 5 "diff " $line]} { if {![regexp {^diff (--cc|--git) } $line m type]} { - set line [encoding convertfrom $line] + set line [encoding convertfrom utf-8 $line] $ctext insert end "$line\n" hunksep continue } @@ -8238,7 +8378,7 @@ proc parseblobdiffline {ids line} { makediffhdr $fname $ids } elseif {![string compare -length 16 "* Unmerged path " $line]} { - set fname [encoding convertfrom [string range $line 16 end]] + set fname [encoding convertfrom utf-8 [string range $line 16 end]] $ctext insert end "\n" set curdiffstart [$ctext index "end - 1c"] lappend ctext_file_names $fname @@ -8291,7 +8431,7 @@ proc parseblobdiffline {ids line} { if {[string index $fname 0] eq "\""} { set fname [lindex $fname 0] } - set fname [encoding convertfrom $fname] + set fname [encoding convertfrom utf-8 $fname] set i [lsearch -exact $treediffs($ids) $fname] if {$i >= 0} { setinlist difffilestart $i $curdiffstart @@ -8310,6 +8450,7 @@ proc parseblobdiffline {ids line} { set diffinhdr 0 return } + set line [encoding convertfrom utf-8 $line] $ctext insert end "$line\n" filesep } else { @@ -10068,7 +10209,7 @@ proc showrefs {} { text $top.list -background $bgcolor -foreground $fgcolor \ -selectbackground $selectbgcolor -font mainfont \ -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \ - -width 30 -height 20 -cursor $maincursor \ + -width 60 -height 20 -cursor $maincursor \ -spacing1 1 -spacing3 1 -state disabled $top.list tag configure highlight -background $selectbgcolor if {![lsearch -exact $bglist $top.list]} { @@ -12305,7 +12446,7 @@ proc cache_gitattr {attr pathlist} { foreach row [split $rlist "\n"] { if {[regexp "(.*): $attr: (.*)" $row m path value]} { if {[string index $path 0] eq "\""} { - set path [encoding convertfrom [lindex $path 0]] + set path [encoding convertfrom utf-8 [lindex $path 0]] } set path_attr_cache($attr,$path) $value } @@ -12335,7 +12476,6 @@ if { [info exists ::env(GITK_MSGSDIR)] } { set gitk_prefix [file dirname [file dirname [file normalize $argv0]]] set gitk_libdir [file join $gitk_prefix share gitk lib] set gitk_msgsdir [file join $gitk_libdir msgs] - unset gitk_prefix } ## Internationalization (i18n) through msgcat and gettext. See @@ -12637,6 +12777,7 @@ set nullid2 "0000000000000000000000000000000000000001" set nullfile "/dev/null" set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}] +set have_tk86 [expr {[package vcompare $tk_version "8.6"] >= 0}] if {![info exists have_ttk]} { set have_ttk [llength [info commands ::ttk::style]] } @@ -12701,28 +12842,32 @@ if {[expr {[exec git rev-parse --is-inside-work-tree] == "true"}]} { set worktree [gitworktree] setcoords makewindow -catch { - image create photo gitlogo -width 16 -height 16 - - image create photo gitlogominus -width 4 -height 2 - gitlogominus put #C00000 -to 0 0 4 2 - gitlogo copy gitlogominus -to 1 5 - gitlogo copy gitlogominus -to 6 5 - gitlogo copy gitlogominus -to 11 5 - image delete gitlogominus - - image create photo gitlogoplus -width 4 -height 4 - gitlogoplus put #008000 -to 1 0 3 4 - gitlogoplus put #008000 -to 0 1 4 3 - gitlogo copy gitlogoplus -to 1 9 - gitlogo copy gitlogoplus -to 6 9 - gitlogo copy gitlogoplus -to 11 9 - image delete gitlogoplus - - image create photo gitlogo32 -width 32 -height 32 - gitlogo32 copy gitlogo -zoom 2 2 - - wm iconphoto . -default gitlogo gitlogo32 +if {$::tcl_platform(platform) eq {windows} && [file exists $gitk_prefix/etc/git.ico]} { + wm iconbitmap . -default $gitk_prefix/etc/git.ico +} else { + catch { + image create photo gitlogo -width 16 -height 16 + + image create photo gitlogominus -width 4 -height 2 + gitlogominus put #C00000 -to 0 0 4 2 + gitlogo copy gitlogominus -to 1 5 + gitlogo copy gitlogominus -to 6 5 + gitlogo copy gitlogominus -to 11 5 + image delete gitlogominus + + image create photo gitlogoplus -width 4 -height 4 + gitlogoplus put #008000 -to 1 0 3 4 + gitlogoplus put #008000 -to 0 1 4 3 + gitlogo copy gitlogoplus -to 1 9 + gitlogo copy gitlogoplus -to 6 9 + gitlogo copy gitlogoplus -to 11 9 + image delete gitlogoplus + + image create photo gitlogo32 -width 32 -height 32 + gitlogo32 copy gitlogo -zoom 2 2 + + wm iconphoto . -default gitlogo gitlogo32 + } } # wait for the window to become visible if {![winfo viewable .]} {tkwait visibility .} diff --git a/gitk-git/meson.build b/gitk-git/meson.build new file mode 100644 index 0000000000..ca3c0cec58 --- /dev/null +++ b/gitk-git/meson.build @@ -0,0 +1,30 @@ +project('gitk') + +shell = find_program('sh') +wish = find_program('wish') + +# Verify that dependencies of "generate-tcl.sh" are satisfied. +foreach dependency : [ 'chmod', 'mv', 'sed' ] + find_program(dependency) +endforeach + +custom_target( + command: [ + shell, + meson.current_source_dir() / 'generate-tcl.sh', + wish.full_path(), + '@INPUT@', + '@OUTPUT@', + ], + input: 'gitk', + output: 'gitk', + depend_files: [ + 'generate-tcl.sh', + ], + install: true, + install_dir: get_option('bindir'), +) + +if find_program('msgfmt').found() + subdir('po') +endif diff --git a/gitk-git/po/meson.build b/gitk-git/po/meson.build new file mode 100644 index 0000000000..b1ed019828 --- /dev/null +++ b/gitk-git/po/meson.build @@ -0,0 +1,19 @@ +import('i18n').gettext('gitk', + languages: [ + 'bg', + 'ca', + 'de', + 'es', + 'fr', + 'hu', + 'it', + 'ja', + 'pt_br', + 'pt_pt', + 'ru', + 'sv', + 'vi', + 'zh_cn', + ], + install: true, +) @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -351,7 +350,7 @@ struct git_graph *graph_init(struct rev_info *opt) if (!column_colors) { char *string; - if (git_config_get_string("log.graphcolors", &string)) { + if (repo_config_get_string(opt->repo, "log.graphcolors", &string)) { /* not configured -- use default */ graph_set_column_colors(column_colors_ansi, column_colors_ansi_max); @@ -193,17 +193,18 @@ struct object_id { int algo; /* XXX requires 4-byte alignment */ }; -#define GET_OID_QUIETLY 01 -#define GET_OID_COMMIT 02 -#define GET_OID_COMMITTISH 04 -#define GET_OID_TREE 010 -#define GET_OID_TREEISH 020 -#define GET_OID_BLOB 040 -#define GET_OID_FOLLOW_SYMLINKS 0100 -#define GET_OID_RECORD_PATH 0200 -#define GET_OID_ONLY_TO_DIE 04000 -#define GET_OID_REQUIRE_PATH 010000 -#define GET_OID_HASH_ANY 020000 +#define GET_OID_QUIETLY 01 +#define GET_OID_COMMIT 02 +#define GET_OID_COMMITTISH 04 +#define GET_OID_TREE 010 +#define GET_OID_TREEISH 020 +#define GET_OID_BLOB 040 +#define GET_OID_FOLLOW_SYMLINKS 0100 +#define GET_OID_RECORD_PATH 0200 +#define GET_OID_ONLY_TO_DIE 04000 +#define GET_OID_REQUIRE_PATH 010000 +#define GET_OID_HASH_ANY 020000 +#define GET_OID_SKIP_AMBIGUITY_CHECK 040000 #define GET_OID_DISAMBIGUATORS \ (GET_OID_COMMIT | GET_OID_COMMITTISH | \ @@ -234,19 +235,20 @@ enum get_oid_result { #endif /* A suitably aligned type for stack allocations of hash contexts. */ -union git_hash_ctx { - git_SHA_CTX sha1; - git_SHA_CTX_unsafe sha1_unsafe; - - git_SHA256_CTX sha256; +struct git_hash_ctx { + const struct git_hash_algo *algop; + union { + git_SHA_CTX sha1; + git_SHA_CTX_unsafe sha1_unsafe; + git_SHA256_CTX sha256; + } state; }; -typedef union git_hash_ctx git_hash_ctx; -typedef void (*git_hash_init_fn)(git_hash_ctx *ctx); -typedef void (*git_hash_clone_fn)(git_hash_ctx *dst, const git_hash_ctx *src); -typedef void (*git_hash_update_fn)(git_hash_ctx *ctx, const void *in, size_t len); -typedef void (*git_hash_final_fn)(unsigned char *hash, git_hash_ctx *ctx); -typedef void (*git_hash_final_oid_fn)(struct object_id *oid, git_hash_ctx *ctx); +typedef void (*git_hash_init_fn)(struct git_hash_ctx *ctx); +typedef void (*git_hash_clone_fn)(struct git_hash_ctx *dst, const struct git_hash_ctx *src); +typedef void (*git_hash_update_fn)(struct git_hash_ctx *ctx, const void *in, size_t len); +typedef void (*git_hash_final_fn)(unsigned char *hash, struct git_hash_ctx *ctx); +typedef void (*git_hash_final_oid_fn)(struct object_id *oid, struct git_hash_ctx *ctx); struct git_hash_algo { /* @@ -282,21 +284,6 @@ struct git_hash_algo { /* The hash finalization function for object IDs. */ git_hash_final_oid_fn final_oid_fn; - /* The non-cryptographic hash initialization function. */ - git_hash_init_fn unsafe_init_fn; - - /* The non-cryptographic hash context cloning function. */ - git_hash_clone_fn unsafe_clone_fn; - - /* The non-cryptographic hash update function. */ - git_hash_update_fn unsafe_update_fn; - - /* The non-cryptographic hash finalization function. */ - git_hash_final_fn unsafe_final_fn; - - /* The non-cryptographic hash finalization function. */ - git_hash_final_oid_fn unsafe_final_oid_fn; - /* The OID of the empty tree. */ const struct object_id *empty_tree; @@ -305,9 +292,32 @@ struct git_hash_algo { /* The all-zeros OID. */ const struct object_id *null_oid; + + /* The unsafe variant of this hash function, if one exists. */ + const struct git_hash_algo *unsafe; }; extern const struct git_hash_algo hash_algos[GIT_HASH_NALGOS]; +static inline void git_hash_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src) +{ + src->algop->clone_fn(dst, src); +} + +static inline void git_hash_update(struct git_hash_ctx *ctx, const void *in, size_t len) +{ + ctx->algop->update_fn(ctx, in, len); +} + +static inline void git_hash_final(unsigned char *hash, struct git_hash_ctx *ctx) +{ + ctx->algop->final_fn(hash, ctx); +} + +static inline void git_hash_final_oid(struct object_id *oid, struct git_hash_ctx *ctx) +{ + ctx->algop->final_oid_fn(oid, ctx); +} + /* * Return a GIT_HASH_* constant based on the name. Returns GIT_HASH_UNKNOWN if * the name doesn't match a known algorithm. @@ -320,9 +330,17 @@ int hash_algo_by_length(int len); /* Identical, except for a pointer to struct git_hash_algo. */ static inline int hash_algo_by_ptr(const struct git_hash_algo *p) { - return p - hash_algos; + size_t i; + for (i = 0; i < GIT_HASH_NALGOS; i++) { + const struct git_hash_algo *algop = &hash_algos[i]; + if (p == algop) + return i; + } + return GIT_HASH_UNKNOWN; } +const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop); + const struct object_id *null_oid(void); static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop) @@ -2,6 +2,7 @@ #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" +#include "git-zlib.h" #include "config.h" #include "builtin.h" #include "exec-cmd.h" @@ -552,10 +553,34 @@ struct help_unknown_cmd_config { struct cmdnames aliases; }; +#define AUTOCORRECT_SHOW (-4) #define AUTOCORRECT_PROMPT (-3) #define AUTOCORRECT_NEVER (-2) #define AUTOCORRECT_IMMEDIATELY (-1) +static int parse_autocorrect(const char *value) +{ + switch (git_parse_maybe_bool_text(value)) { + case 1: + return AUTOCORRECT_IMMEDIATELY; + case 0: + return AUTOCORRECT_SHOW; + default: /* other random text */ + break; + } + + if (!strcmp(value, "prompt")) + return AUTOCORRECT_PROMPT; + if (!strcmp(value, "never")) + return AUTOCORRECT_NEVER; + if (!strcmp(value, "immediate")) + return AUTOCORRECT_IMMEDIATELY; + if (!strcmp(value, "show")) + return AUTOCORRECT_SHOW; + + return 0; +} + static int git_unknown_cmd_config(const char *var, const char *value, const struct config_context *ctx, void *cb) @@ -564,20 +589,17 @@ static int git_unknown_cmd_config(const char *var, const char *value, const char *p; if (!strcmp(var, "help.autocorrect")) { - if (!value) - return config_error_nonbool(var); - if (!strcmp(value, "never")) { - cfg->autocorrect = AUTOCORRECT_NEVER; - } else if (!strcmp(value, "immediate")) { - cfg->autocorrect = AUTOCORRECT_IMMEDIATELY; - } else if (!strcmp(value, "prompt")) { - cfg->autocorrect = AUTOCORRECT_PROMPT; - } else { - int v = git_config_int(var, value, ctx->kvi); - cfg->autocorrect = (v < 0) - ? AUTOCORRECT_IMMEDIATELY : v; + int v = parse_autocorrect(value); + + if (!v) { + v = git_config_int(var, value, ctx->kvi); + if (v < 0 || v == 1) + v = AUTOCORRECT_IMMEDIATELY; } + + cfg->autocorrect = v; } + /* Also use aliases for command lookup */ if (skip_prefix(var, "alias.", &p)) add_cmdname(&cfg->aliases, p, strlen(p)); @@ -695,7 +717,8 @@ char *help_unknown_cmd(const char *cmd) n++) ; /* still counting */ } - if (cfg.autocorrect && n == 1 && SIMILAR_ENOUGH(best_similarity)) { + if (cfg.autocorrect && cfg.autocorrect != AUTOCORRECT_SHOW && n == 1 && + SIMILAR_ENOUGH(best_similarity)) { char *assumed = xstrdup(main_cmds.names[0]->name); fprintf_ln(stderr, @@ -775,7 +798,9 @@ void get_version_info(struct strbuf *buf, int show_build_options) #if defined OPENSSL_VERSION_TEXT strbuf_addf(buf, "OpenSSL: %s\n", OPENSSL_VERSION_TEXT); #endif -#if defined ZLIB_VERSION +#if defined ZLIBNG_VERSION + strbuf_addf(buf, "zlib-ng: %s\n", ZLIBNG_VERSION); +#elif defined ZLIB_VERSION strbuf_addf(buf, "zlib: %s\n", ZLIB_VERSION); #endif } @@ -16,8 +16,7 @@ const char *find_hook(struct repository *r, const char *name) int found_hook; - strbuf_reset(&path); - strbuf_repo_git_path(&path, r, "hooks/%s", name); + repo_git_path_replace(r, &path, "hooks/%s", name); found_hook = access(path.buf, X_OK) >= 0; #ifdef STRIP_EXTENSION if (!found_hook) { diff --git a/http-backend.c b/http-backend.c index 33cf378282..50b2858fad 100644 --- a/http-backend.c +++ b/http-backend.c @@ -183,7 +183,7 @@ static void send_strbuf(struct strbuf *hdr, static void send_local_file(struct strbuf *hdr, const char *the_type, const char *name) { - char *p = git_pathdup("%s", name); + char *p = repo_git_path(the_repository, "%s", name); size_t buf_alloc = 8192; char *buf = xmalloc(buf_alloc); int fd; diff --git a/http-push.c b/http-push.c index 43da1c7cd3..1b030d96f4 100644 --- a/http-push.c +++ b/http-push.c @@ -760,7 +760,7 @@ static void handle_lockprop_ctx(struct xml_ctx *ctx, int tag_closed) static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed) { struct remote_lock *lock = (struct remote_lock *)ctx->userData; - git_hash_ctx hash_ctx; + struct git_hash_ctx hash_ctx; unsigned char lock_token_hash[GIT_MAX_RAWSZ]; if (tag_closed && ctx->cdata) { @@ -774,8 +774,8 @@ static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed) lock->token = xstrdup(ctx->cdata); the_hash_algo->init_fn(&hash_ctx); - the_hash_algo->update_fn(&hash_ctx, lock->token, strlen(lock->token)); - the_hash_algo->final_fn(lock_token_hash, &hash_ctx); + git_hash_update(&hash_ctx, lock->token, strlen(lock->token)); + git_hash_final(lock_token_hash, &hash_ctx); lock->tmpfile_suffix[0] = '_'; memcpy(lock->tmpfile_suffix + 1, hash_to_hex(lock_token_hash), the_hash_algo->hexsz); @@ -598,8 +598,7 @@ static void init_curl_http_auth(CURL *result) { if ((!http_auth.username || !*http_auth.username) && (!http_auth.credential || !*http_auth.credential)) { - int empty_auth = curl_empty_auth_enabled(); - if ((empty_auth != -1 && !always_auth_proactively()) || empty_auth == 1) { + if (!always_auth_proactively() && curl_empty_auth_enabled()) { curl_easy_setopt(result, CURLOPT_USERPWD, ":"); return; } else if (!always_auth_proactively()) { @@ -609,7 +608,7 @@ static void init_curl_http_auth(CURL *result) } } - credential_fill(&http_auth, 1); + credential_fill(the_repository, &http_auth, 1); if (http_auth.password) { if (always_auth_proactively()) { @@ -652,7 +651,7 @@ static void init_curl_proxy_auth(CURL *result) { if (proxy_auth.username) { if (!proxy_auth.password && !proxy_auth.credential) - credential_fill(&proxy_auth, 1); + credential_fill(the_repository, &proxy_auth, 1); set_proxyauth_name_password(result); } @@ -686,7 +685,7 @@ static int has_cert_password(void) cert_auth.host = xstrdup(""); cert_auth.username = xstrdup(""); cert_auth.path = xstrdup(ssl_cert); - credential_fill(&cert_auth, 0); + credential_fill(the_repository, &cert_auth, 0); } return 1; } @@ -700,7 +699,7 @@ static int has_proxy_cert_password(void) proxy_cert_auth.host = xstrdup(""); proxy_cert_auth.username = xstrdup(""); proxy_cert_auth.path = xstrdup(http_proxy_ssl_cert); - credential_fill(&proxy_cert_auth, 0); + credential_fill(the_repository, &proxy_cert_auth, 0); } return 1; } @@ -1784,9 +1783,9 @@ static int handle_curl_result(struct slot_results *results) curl_errorstr, sizeof(curl_errorstr)); if (results->curl_result == CURLE_OK) { - credential_approve(&http_auth); - credential_approve(&proxy_auth); - credential_approve(&cert_auth); + credential_approve(the_repository, &http_auth); + credential_approve(the_repository, &proxy_auth); + credential_approve(the_repository, &cert_auth); return HTTP_OK; } else if (results->curl_result == CURLE_SSL_CERTPROBLEM) { /* @@ -1795,7 +1794,7 @@ static int handle_curl_result(struct slot_results *results) * with the certificate. So we reject the credential to * avoid caching or saving a bad password. */ - credential_reject(&cert_auth); + credential_reject(the_repository, &cert_auth); return HTTP_NOAUTH; } else if (results->curl_result == CURLE_SSL_PINNEDPUBKEYNOTMATCH) { return HTTP_NOMATCHPUBLICKEY; @@ -1808,7 +1807,7 @@ static int handle_curl_result(struct slot_results *results) credential_clear_secrets(&http_auth); return HTTP_REAUTH; } - credential_reject(&http_auth); + credential_reject(the_repository, &http_auth); if (always_auth_proactively()) http_proactive_auth = PROACTIVE_AUTH_NONE; return HTTP_NOAUTH; @@ -1822,7 +1821,7 @@ static int handle_curl_result(struct slot_results *results) } } else { if (results->http_connectcode == 407) - credential_reject(&proxy_auth); + credential_reject(the_repository, &proxy_auth); if (!curl_errorstr[0]) strlcpy(curl_errorstr, curl_easy_strerror(results->curl_result), @@ -2210,7 +2209,7 @@ static int http_request_reauth(const char *url, int ret; if (always_auth_proactively()) - credential_fill(&http_auth, 1); + credential_fill(the_repository, &http_auth, 1); ret = http_request(url, result, target, options); @@ -2251,7 +2250,7 @@ static int http_request_reauth(const char *url, BUG("Unknown http_request target"); } - credential_fill(&http_auth, 1); + credential_fill(the_repository, &http_auth, 1); ret = http_request(url, result, target, options); } @@ -2597,8 +2596,8 @@ static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb, freq->stream.next_out = expn; freq->stream.avail_out = sizeof(expn); freq->zret = git_inflate(&freq->stream, Z_SYNC_FLUSH); - the_hash_algo->update_fn(&freq->c, expn, - sizeof(expn) - freq->stream.avail_out); + git_hash_update(&freq->c, expn, + sizeof(expn) - freq->stream.avail_out); } while (freq->stream.avail_in && freq->zret == Z_OK); return nmemb; } @@ -2763,7 +2762,7 @@ int finish_http_object_request(struct http_object_request *freq) return -1; } - the_hash_algo->final_oid_fn(&freq->real_oid, &freq->c); + git_hash_final_oid(&freq->real_oid, &freq->c); if (freq->zret != Z_STREAM_END) { unlink_or_warn(freq->tmpfile.buf); return -1; @@ -228,7 +228,7 @@ struct http_object_request { long http_code; struct object_id oid; struct object_id real_oid; - git_hash_ctx c; + struct git_hash_ctx c; git_zstream stream; int zret; int rename; @@ -59,7 +59,7 @@ static struct passwd *xgetpwuid_self(int *is_bogus) static void copy_gecos(const struct passwd *w, struct strbuf *name) { - char *src; + const char *src; /* Traditionally GECOS field had office phone numbers etc, separated * with commas. Also & stands for capitalized form of the login name. diff --git a/imap-send.c b/imap-send.c index 68ab1aea83..6c8f84e836 100644 --- a/imap-send.c +++ b/imap-send.c @@ -922,7 +922,7 @@ static void server_fill_credential(struct imap_server_conf *srvc, struct credent cred->username = xstrdup_or_null(srvc->user); cred->password = xstrdup_or_null(srvc->pass); - credential_fill(cred, 1); + credential_fill(the_repository, cred, 1); if (!srvc->user) srvc->user = xstrdup(cred->username); @@ -1123,7 +1123,7 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, const c } /* !preauth */ if (cred.username) - credential_approve(&cred); + credential_approve(the_repository, &cred); credential_clear(&cred); /* check the target mailbox exists */ @@ -1150,7 +1150,7 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, const c bail: if (cred.username) - credential_reject(&cred); + credential_reject(the_repository, &cred); credential_clear(&cred); out: @@ -1492,9 +1492,9 @@ static int curl_append_msgs_to_imap(struct imap_server_conf *server, if (cred.username) { if (res == CURLE_OK) - credential_approve(&cred); + credential_approve(the_repository, &cred); else if (res == CURLE_LOGIN_DENIED) - credential_reject(&cred); + credential_reject(the_repository, &cred); } credential_clear(&cred); diff --git a/iterator.h b/iterator.h index 0f6900e43a..6b77dcc262 100644 --- a/iterator.h +++ b/iterator.h @@ -12,7 +12,7 @@ #define ITER_OK 0 /* - * The iterator is exhausted and has been freed. + * The iterator is exhausted. */ #define ITER_DONE -1 diff --git a/list-objects-filter-options.h b/list-objects-filter-options.h index 55fab8563d..7b2108b986 100644 --- a/list-objects-filter-options.h +++ b/list-objects-filter-options.h @@ -82,7 +82,7 @@ void list_objects_filter_init(struct list_objects_filter_options *filter_options * "filter" SP <arg> * * The filter keyword will be used by many commands. - * See Documentation/rev-list-options.txt for allowed values for <arg>. + * See Documentation/rev-list-options.adoc for allowed values for <arg>. * * Capture the given arg as the "filter_spec". This can be forwarded to * subordinate commands when necessary (although it's better to pass it through diff --git a/log-tree.c b/log-tree.c index d08eb672a9..8b184d6776 100644 --- a/log-tree.c +++ b/log-tree.c @@ -1042,7 +1042,7 @@ static int do_remerge_diff(struct rev_info *opt, * into the alternative object store list as the primary. */ if (opt->remerge_diff && !opt->remerge_objdir) { - opt->remerge_objdir = tmp_objdir_create("remerge-diff"); + opt->remerge_objdir = tmp_objdir_create(the_repository, "remerge-diff"); if (!opt->remerge_objdir) return error(_("unable to create temporary object directory")); tmp_objdir_replace_primary_odb(opt->remerge_objdir, 1); @@ -75,7 +75,7 @@ static int load_one_loose_object_map(struct repository *repo, struct object_dire insert_loose_map(dir, repo->hash_algo->empty_blob, repo->compat_hash_algo->empty_blob); insert_loose_map(dir, repo->hash_algo->null_oid, repo->compat_hash_algo->null_oid); - strbuf_git_common_path(&path, repo, "objects/loose-object-idx"); + repo_common_path_replace(repo, &path, "objects/loose-object-idx"); fp = fopen(path.buf, "rb"); if (!fp) { strbuf_release(&path); @@ -133,7 +133,7 @@ int repo_write_loose_object_map(struct repository *repo) if (!should_use_loose_object_map(repo)) return 0; - strbuf_git_common_path(&path, repo, "objects/loose-object-idx"); + repo_common_path_replace(repo, &path, "objects/loose-object-idx"); fd = hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1); iter = kh_begin(map); if (write_in_full(fd, loose_object_header, strlen(loose_object_header)) < 0) @@ -174,7 +174,7 @@ static int write_one_object(struct repository *repo, const struct object_id *oid struct stat st; struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT; - strbuf_git_common_path(&path, repo, "objects/loose-object-idx"); + repo_common_path_replace(repo, &path, "objects/loose-object-idx"); hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1); fd = open(path.buf, O_WRONLY | O_CREAT | O_APPEND, 0666); @@ -190,7 +190,7 @@ static int write_one_object(struct repository *repo, const struct object_id *oid goto errout; if (close(fd)) goto errout; - adjust_shared_perm(path.buf); + adjust_shared_perm(repo, path.buf); rollback_lock_file(&lock); strbuf_release(&buf); strbuf_release(&path); diff --git a/mailinfo.c b/mailinfo.c index aa263bf490..7b001fa5db 100644 --- a/mailinfo.c +++ b/mailinfo.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -1269,7 +1268,7 @@ static int git_mailinfo_config(const char *var, const char *value, return 0; } -void setup_mailinfo(struct mailinfo *mi) +void setup_mailinfo(struct repository *r, struct mailinfo *mi) { memset(mi, 0, sizeof(*mi)); strbuf_init(&mi->name, 0); @@ -1281,7 +1280,7 @@ void setup_mailinfo(struct mailinfo *mi) mi->header_stage = 1; mi->use_inbody_headers = 1; mi->content_top = mi->content; - git_config(git_mailinfo_config, mi); + repo_config(r, git_mailinfo_config, mi); } void clear_mailinfo(struct mailinfo *mi) diff --git a/mailinfo.h b/mailinfo.h index f2ffd0349e..1f20664165 100644 --- a/mailinfo.h +++ b/mailinfo.h @@ -5,6 +5,8 @@ #define MAX_BOUNDARIES 5 +struct repository; + enum quoted_cr_action { quoted_cr_unset = -1, quoted_cr_nowarn, @@ -49,7 +51,7 @@ struct mailinfo { }; int mailinfo_parse_quoted_cr_action(const char *actionstr, int *action); -void setup_mailinfo(struct mailinfo *); +void setup_mailinfo(struct repository *r, struct mailinfo *); int mailinfo(struct mailinfo *, const char *msg, const char *patch); void clear_mailinfo(struct mailinfo *); diff --git a/match-trees.c b/match-trees.c index a1c8b91eae..ef14ceb594 100644 --- a/match-trees.c +++ b/match-trees.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -8,6 +7,7 @@ #include "tree.h" #include "tree-walk.h" #include "object-store-ll.h" +#include "repository.h" static int score_missing(unsigned mode) { @@ -54,14 +54,15 @@ static int score_matches(unsigned mode1, unsigned mode2) return score; } -static void *fill_tree_desc_strict(struct tree_desc *desc, +static void *fill_tree_desc_strict(struct repository *r, + struct tree_desc *desc, const struct object_id *hash) { void *buffer; enum object_type type; unsigned long size; - buffer = repo_read_object_file(the_repository, hash, &type, &size); + buffer = repo_read_object_file(r, hash, &type, &size); if (!buffer) die("unable to read tree (%s)", oid_to_hex(hash)); if (type != OBJ_TREE) @@ -80,12 +81,13 @@ static int base_name_entries_compare(const struct name_entry *a, /* * Inspect two trees, and give a score that tells how similar they are. */ -static int score_trees(const struct object_id *hash1, const struct object_id *hash2) +static int score_trees(struct repository *r, + const struct object_id *hash1, const struct object_id *hash2) { struct tree_desc one; struct tree_desc two; - void *one_buf = fill_tree_desc_strict(&one, hash1); - void *two_buf = fill_tree_desc_strict(&two, hash2); + void *one_buf = fill_tree_desc_strict(r, &one, hash1); + void *two_buf = fill_tree_desc_strict(r, &two, hash2); int score = 0; for (;;) { @@ -133,7 +135,8 @@ static int score_trees(const struct object_id *hash1, const struct object_id *ha /* * Match one itself and its subtrees with two and pick the best match. */ -static void match_trees(const struct object_id *hash1, +static void match_trees(struct repository *r, + const struct object_id *hash1, const struct object_id *hash2, int *best_score, char **best_match, @@ -141,7 +144,7 @@ static void match_trees(const struct object_id *hash1, int recurse_limit) { struct tree_desc one; - void *one_buf = fill_tree_desc_strict(&one, hash1); + void *one_buf = fill_tree_desc_strict(r, &one, hash1); while (one.size) { const char *path; @@ -152,7 +155,7 @@ static void match_trees(const struct object_id *hash1, elem = tree_entry_extract(&one, &path, &mode); if (!S_ISDIR(mode)) goto next; - score = score_trees(elem, hash2); + score = score_trees(r, elem, hash2); if (*best_score < score) { free(*best_match); *best_match = xstrfmt("%s%s", base, path); @@ -160,7 +163,7 @@ static void match_trees(const struct object_id *hash1, } if (recurse_limit) { char *newbase = xstrfmt("%s%s/", base, path); - match_trees(elem, hash2, best_score, best_match, + match_trees(r, elem, hash2, best_score, best_match, newbase, recurse_limit - 1); free(newbase); } @@ -175,7 +178,8 @@ static void match_trees(const struct object_id *hash1, * A tree "oid1" has a subdirectory at "prefix". Come up with a tree object by * replacing it with another tree "oid2". */ -static int splice_tree(const struct object_id *oid1, const char *prefix, +static int splice_tree(struct repository *r, + const struct object_id *oid1, const char *prefix, const struct object_id *oid2, struct object_id *result) { char *subpath; @@ -194,7 +198,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix, if (*subpath) subpath++; - buf = repo_read_object_file(the_repository, oid1, &type, &sz); + buf = repo_read_object_file(r, oid1, &type, &sz); if (!buf) die("cannot read tree %s", oid_to_hex(oid1)); init_tree_desc(&desc, oid1, buf, sz); @@ -232,15 +236,15 @@ static int splice_tree(const struct object_id *oid1, const char *prefix, oid_to_hex(oid1)); if (*subpath) { struct object_id tree_oid; - oidread(&tree_oid, rewrite_here, the_repository->hash_algo); - status = splice_tree(&tree_oid, subpath, oid2, &subtree); + oidread(&tree_oid, rewrite_here, r->hash_algo); + status = splice_tree(r, &tree_oid, subpath, oid2, &subtree); if (status) return status; rewrite_with = &subtree; } else { rewrite_with = oid2; } - hashcpy(rewrite_here, rewrite_with->hash, the_repository->hash_algo); + hashcpy(rewrite_here, rewrite_with->hash, r->hash_algo); status = write_object_file(buf, sz, OBJ_TREE, result); free(buf); return status; @@ -271,7 +275,7 @@ void shift_tree(struct repository *r, if (!depth_limit) depth_limit = 2; - add_score = del_score = score_trees(hash1, hash2); + add_score = del_score = score_trees(r, hash1, hash2); add_prefix = xcalloc(1, 1); del_prefix = xcalloc(1, 1); @@ -279,13 +283,13 @@ void shift_tree(struct repository *r, * See if one's subtree resembles two; if so we need to prefix * two with a few fake trees to match the prefix. */ - match_trees(hash1, hash2, &add_score, &add_prefix, "", depth_limit); + match_trees(r, hash1, hash2, &add_score, &add_prefix, "", depth_limit); /* * See if two's subtree resembles one; if so we need to * pick only subtree of two. */ - match_trees(hash2, hash1, &del_score, &del_prefix, "", depth_limit); + match_trees(r, hash2, hash1, &del_score, &del_prefix, "", depth_limit); /* Assume we do not have to do any shifting */ oidcpy(shifted, hash2); @@ -306,7 +310,7 @@ void shift_tree(struct repository *r, if (!*add_prefix) goto out; - splice_tree(hash1, add_prefix, hash2, shifted); + splice_tree(r, hash1, add_prefix, hash2, shifted); out: free(add_prefix); @@ -340,16 +344,16 @@ void shift_tree_by(struct repository *r, if (candidate == 3) { /* Both are plausible -- we need to evaluate the score */ - int best_score = score_trees(hash1, hash2); + int best_score = score_trees(r, hash1, hash2); int score; candidate = 0; - score = score_trees(&sub1, hash2); + score = score_trees(r, &sub1, hash2); if (score > best_score) { candidate = 1; best_score = score; } - score = score_trees(&sub2, hash1); + score = score_trees(r, &sub2, hash1); if (score > best_score) candidate = 2; } @@ -365,7 +369,7 @@ void shift_tree_by(struct repository *r, * shift tree2 down by adding shift_prefix above it * to match tree1. */ - splice_tree(hash1, shift_prefix, hash2, shifted); + splice_tree(r, hash1, shift_prefix, hash2, shifted); else /* * shift tree2 up by removing shift_prefix from it diff --git a/merge-ort-wrappers.c b/merge-ort-wrappers.c index d6f6135996..c54d56b344 100644 --- a/merge-ort-wrappers.c +++ b/merge-ort-wrappers.c @@ -1,9 +1,13 @@ #include "git-compat-util.h" #include "gettext.h" #include "hash.h" +#include "hex.h" +#include "lockfile.h" #include "merge-ort.h" #include "merge-ort-wrappers.h" #include "read-cache-ll.h" +#include "repository.h" +#include "tag.h" #include "tree.h" #include "commit.h" @@ -29,6 +33,7 @@ int merge_ort_nonrecursive(struct merge_options *opt, struct tree *merge_base) { struct merge_result result; + int show_msgs; if (unclean(opt, head)) return -1; @@ -38,9 +43,10 @@ int merge_ort_nonrecursive(struct merge_options *opt, return 1; } + show_msgs = !!opt->verbosity; memset(&result, 0, sizeof(result)); merge_incore_nonrecursive(opt, merge_base, head, merge, &result); - merge_switch_to_result(opt, head, &result, 1, 1); + merge_switch_to_result(opt, head, &result, 1, show_msgs); return result.clean; } @@ -53,14 +59,76 @@ int merge_ort_recursive(struct merge_options *opt, { struct tree *head = repo_get_commit_tree(opt->repo, side1); struct merge_result tmp; + int show_msgs; if (unclean(opt, head)) return -1; + show_msgs = !!opt->verbosity; memset(&tmp, 0, sizeof(tmp)); merge_incore_recursive(opt, merge_bases, side1, side2, &tmp); - merge_switch_to_result(opt, head, &tmp, 1, 1); + merge_switch_to_result(opt, head, &tmp, 1, show_msgs); *result = NULL; return tmp.clean; } + +static struct commit *get_ref(struct repository *repo, + const struct object_id *oid, + const char *name) +{ + struct object *object; + + object = deref_tag(repo, parse_object(repo, oid), + name, strlen(name)); + if (!object) + return NULL; + if (object->type == OBJ_TREE) + return make_virtual_commit(repo, (struct tree*)object, name); + if (object->type != OBJ_COMMIT) + return NULL; + if (repo_parse_commit(repo, (struct commit *)object)) + return NULL; + return (struct commit *)object; +} + +int merge_ort_generic(struct merge_options *opt, + const struct object_id *head, + const struct object_id *merge, + int num_merge_bases, + const struct object_id *merge_bases, + struct commit **result) +{ + int clean; + struct lock_file lock = LOCK_INIT; + struct commit *head_commit = get_ref(opt->repo, head, opt->branch1); + struct commit *next_commit = get_ref(opt->repo, merge, opt->branch2); + struct commit_list *ca = NULL; + + if (merge_bases) { + int i; + for (i = 0; i < num_merge_bases; ++i) { + struct commit *base; + if (!(base = get_ref(opt->repo, &merge_bases[i], + oid_to_hex(&merge_bases[i])))) + return error(_("Could not parse object '%s'"), + oid_to_hex(&merge_bases[i])); + commit_list_insert(base, &ca); + } + } + + repo_hold_locked_index(opt->repo, &lock, LOCK_DIE_ON_ERROR); + clean = merge_ort_recursive(opt, head_commit, next_commit, ca, + result); + free_commit_list(ca); + if (clean < 0) { + rollback_lock_file(&lock); + return clean; + } + + if (write_locked_index(opt->repo->index, &lock, + COMMIT_LOCK | SKIP_IF_UNCHANGED)) + return error(_("Unable to write index.")); + + return clean ? 0 : 1; +} diff --git a/merge-ort-wrappers.h b/merge-ort-wrappers.h index 90af1f69c5..aeffa1c87b 100644 --- a/merge-ort-wrappers.h +++ b/merge-ort-wrappers.h @@ -22,4 +22,16 @@ int merge_ort_recursive(struct merge_options *opt, const struct commit_list *ancestors, struct commit **result); +/* + * rename-detecting three-way merge. num_merge_bases must be at least 1. + * Recursive ancestor consolidation will be performed if num_merge_bases > 1. + * Wrapper mimicking the old merge_recursive_generic() function. + */ +int merge_ort_generic(struct merge_options *opt, + const struct object_id *head, + const struct object_id *merge, + int num_merge_bases, + const struct object_id *merge_bases, + struct commit **result); + #endif diff --git a/merge-ort.c b/merge-ort.c index 46e78c3ffa..e328511e19 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -3048,7 +3048,8 @@ static int process_renames(struct merge_options *opt, } } - assert(source_deleted || oldinfo->filemask & old_sidemask); + assert(source_deleted || oldinfo->filemask & old_sidemask || + !strcmp(pair->one->path, pair->two->path)); /* Need to check for special types of rename conflicts... */ if (collision && !source_deleted) { @@ -3404,6 +3405,11 @@ static int collect_renames(struct merge_options *opt, pool_diff_free_filepair(&opt->priv->pool, p); continue; } + if (opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_NONE && + p->status == 'R' && 1) { + possibly_cache_new_pair(renames, p, side_index, NULL); + goto skip_directory_renames; + } new_path = check_for_directory_rename(opt, p->two->path, side_index, @@ -3421,6 +3427,7 @@ static int collect_renames(struct merge_options *opt, if (new_path) apply_directory_rename_modifications(opt, p, new_path); +skip_directory_renames: /* * p->score comes back from diffcore_rename_extended() with * the similarity of the renamed file. The similarity is @@ -3448,6 +3455,11 @@ static int detect_and_process_renames(struct merge_options *opt) if (!possible_renames(renames)) goto cleanup; + if (!opt->detect_renames) { + renames->redo_after_renames = 0; + renames->cached_pairs_valid_side = 0; + goto cleanup; + } trace2_region_enter("merge", "regular renames", opt->repo); detection_run |= detect_regular_renames(opt, MERGE_SIDE1); @@ -4878,9 +4890,9 @@ static inline void set_commit_tree(struct commit *c, struct tree *t) c->maybe_tree = t; } -static struct commit *make_virtual_commit(struct repository *repo, - struct tree *tree, - const char *comment) +struct commit *make_virtual_commit(struct repository *repo, + struct tree *tree, + const char *comment) { struct commit *commit = alloc_commit_node(repo); @@ -5020,7 +5032,8 @@ static void merge_start(struct merge_options *opt, struct merge_result *result) trace2_region_leave("merge", "allocate/init", opt->repo); } -static void merge_check_renames_reusable(struct merge_result *result, +static void merge_check_renames_reusable(struct merge_options *opt, + struct merge_result *result, struct tree *merge_base, struct tree *side1, struct tree *side2) @@ -5046,6 +5059,26 @@ static void merge_check_renames_reusable(struct merge_result *result, } /* + * Avoid using cached renames when directory rename detection is + * turned off. Cached renames are far less important in that case, + * and they lead to testcases with an interesting intersection of + * effects from relevant renames optimization, trivial directory + * resolution optimization, and cached renames all converging when + * the target of a cached rename is in a directory that + * collect_merge_info() does not recurse into. To avoid such + * problems, simply disable cached renames for this case (similar + * to the rename/rename(1to1) case; see the "disabling the + * optimization" comment near that case). + * + * This could be revisited in the future; see the commit message + * where this comment was added for some possible pointers. + */ + if (opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_NONE) { + renames->cached_pairs_valid_side = 0; /* neither side valid */ + return; + } + + /* * Handle other cases; note that merge_trees[0..2] will only * be NULL if opti is, or if all three were manually set to * NULL by e.g. rename/rename(1to1) handling. @@ -5186,6 +5219,8 @@ static void merge_ort_internal(struct merge_options *opt, ancestor_name = "empty tree"; } else if (merge_bases) { ancestor_name = "merged common ancestors"; + } else if (opt->ancestor) { + ancestor_name = opt->ancestor; } else { strbuf_add_unique_abbrev(&merge_base_abbrev, &merged_merge_bases->object.oid, @@ -5251,7 +5286,7 @@ void merge_incore_nonrecursive(struct merge_options *opt, trace2_region_enter("merge", "merge_start", opt->repo); assert(opt->ancestor != NULL); - merge_check_renames_reusable(result, merge_base, side1, side2); + merge_check_renames_reusable(opt, result, merge_base, side1, side2); merge_start(opt, result); /* * Record the trees used in this merge, so if there's a next merge in @@ -5275,8 +5310,13 @@ void merge_incore_recursive(struct merge_options *opt, { trace2_region_enter("merge", "incore_recursive", opt->repo); - /* We set the ancestor label based on the merge_bases */ - assert(opt->ancestor == NULL); + /* + * We set the ancestor label based on the merge_bases...but we + * allow one exception through so that builtin/am can override + * with its constructed fake ancestor. + */ + assert(opt->ancestor == NULL || + (merge_bases && !merge_bases->next)); trace2_region_enter("merge", "merge_start", opt->repo); merge_start(opt, result); diff --git a/merge-ort.h b/merge-ort.h index 82f2b3222d..b63bc5424e 100644 --- a/merge-ort.h +++ b/merge-ort.h @@ -44,6 +44,11 @@ struct merge_result { unsigned _properly_initialized; }; +/* Mostly internal function also used by merge-ort-wrappers.c */ +struct commit *make_virtual_commit(struct repository *repo, + struct tree *tree, + const char *comment); + /* * rename-detecting three-way merge with recursive ancestor consolidation. * working tree and index are untouched. diff --git a/merge-recursive.c b/merge-recursive.c index 5dfaf32b2c..884ccf99a5 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -2758,23 +2758,22 @@ static int process_renames(struct merge_options *opt, const struct rename *sre; /* - * FIXME: As string-list.h notes, it's O(n^2) to build a sorted - * string_list one-by-one, but O(n log n) to build it unsorted and - * then sort it. Note that as we build the list, we do not need to - * check if the existing destination path is already in the list, - * because the structure of diffcore_rename guarantees we won't - * have duplicates. + * Note that as we build the list, we do not need to check if the + * existing destination path is already in the list, because the + * structure of diffcore_rename guarantees we won't have duplicates. */ for (i = 0; i < a_renames->nr; i++) { sre = a_renames->items[i].util; - string_list_insert(&a_by_dst, sre->pair->two->path)->util + string_list_append(&a_by_dst, sre->pair->two->path)->util = (void *)sre; } for (i = 0; i < b_renames->nr; i++) { sre = b_renames->items[i].util; - string_list_insert(&b_by_dst, sre->pair->two->path)->util + string_list_append(&b_by_dst, sre->pair->two->path)->util = (void *)sre; } + string_list_sort(&a_by_dst); + string_list_sort(&b_by_dst); for (i = 0, j = 0; i < a_renames->nr || j < b_renames->nr;) { struct string_list *renames1, *renames2Dst; diff --git a/meson.build b/meson.build index 0c1904b94b..33d92c066c 100644 --- a/meson.build +++ b/meson.build @@ -170,36 +170,50 @@ project('git', 'c', meson_version: '>=0.61.0', - version: 'v2.47.GIT', + # The version is only of cosmetic nature, so if we cannot find a shell yet we + # simply don't set up a version at all. This may be the case for example on + # Windows systems, where we first have to bootstrap the host environment. + version: find_program('sh', required: false).found() ? run_command( + 'GIT-VERSION-GEN', meson.current_source_dir(), '--format=@GIT_VERSION@', + capture: true, + check: true, + ).stdout().strip() : 'unknown', + default_options: [ + # Git requires C99 with GNU extensions, which of course isn't supported by + # MSVC. Funny enough, C99 doesn't work with MSVC either, as it has only + # learned to define __STDC_VERSION__ with C11 and later. We thus require + # GNU C99 and fall back to C11. Meson only learned to handle the fallback + # with version 1.3.0, so on older versions we use GNU C99 unconditionally. + 'c_std=' + (meson.version().version_compare('>=1.3.0') ? 'gnu99,c11' : 'gnu99'), + ], ) fs = import('fs') program_path = [] -# Git for Windows provides all the tools we need to build Git. -if host_machine.system() == 'windows' - program_path += [ 'C:/Program Files/Git/bin', 'C:/Program Files/Git/usr/bin' ] +if get_option('sane_tool_path').length() != 0 + program_path = get_option('sane_tool_path') +elif host_machine.system() == 'windows' + # Git for Windows provides all the tools we need to build Git. + program_path = [ 'C:/Program Files/Git/bin', 'C:/Program Files/Git/usr/bin' ] endif cygpath = find_program('cygpath', dirs: program_path, required: false) diff = find_program('diff', dirs: program_path) +git = find_program('git', dirs: program_path, required: false) +sed = find_program('sed', dirs: program_path) shell = find_program('sh', dirs: program_path) tar = find_program('tar', dirs: program_path) -script_environment = environment() -foreach tool : ['cat', 'cut', 'grep', 'sed', 'sort', 'tr', 'uname'] - program = find_program(tool, dirs: program_path) - script_environment.prepend('PATH', fs.parent(program.full_path())) +# Sanity-check that programs required for the build exist. +foreach tool : ['cat', 'cut', 'grep', 'sort', 'tr', 'uname'] + find_program(tool, dirs: program_path) endforeach -git = find_program('git', dirs: program_path, required: false) -if git.found() - script_environment.prepend('PATH', fs.parent(git.full_path())) -endif - -if get_option('sane_tool_path') != '' - script_environment.prepend('PATH', get_option('sane_tool_path')) -endif +script_environment = environment() +foreach path : program_path + script_environment.prepend('PATH', path) +endforeach # The environment used by GIT-VERSION-GEN. Note that we explicitly override # environment variables that might be set by the user. This is by design so @@ -245,10 +259,11 @@ libgit_sources = [ 'commit-graph.c', 'commit-reach.c', 'commit.c', + 'common-exit.c', + 'common-init.c', 'compat/nonblock.c', 'compat/obstack.c', 'compat/terminal.c', - 'compat/zlib-uncompress2.c', 'compiler-tricks/not-constant.c', 'config.c', 'connect.c', @@ -359,6 +374,7 @@ libgit_sources = [ 'patch-delta.c', 'patch-ids.c', 'path.c', + 'path-walk.c', 'pathspec.c', 'pkt-line.c', 'preload-index.c', @@ -463,6 +479,7 @@ libgit_sources = [ 'userdiff.c', 'utf8.c', 'varint.c', + 'version.c', 'versioncmp.c', 'walker.c', 'wildmatch.c', @@ -481,12 +498,20 @@ libgit_sources = [ 'xdiff/xutils.c', ] +libgit_sources += custom_target( + input: 'command-list.txt', + output: 'command-list.h', + command: [shell, meson.current_source_dir() + '/generate-cmdlist.sh', meson.current_source_dir(), '@OUTPUT@'], + env: script_environment, +) + builtin_sources = [ 'builtin/add.c', 'builtin/am.c', 'builtin/annotate.c', 'builtin/apply.c', 'builtin/archive.c', + 'builtin/backfill.c', 'builtin/bisect.c', 'builtin/blame.c', 'builtin/branch.c', @@ -516,6 +541,7 @@ builtin_sources = [ 'builtin/diagnose.c', 'builtin/diff-files.c', 'builtin/diff-index.c', + 'builtin/diff-pairs.c', 'builtin/diff-tree.c', 'builtin/diff.c', 'builtin/difftool.c', @@ -557,7 +583,6 @@ builtin_sources = [ 'builtin/name-rev.c', 'builtin/notes.c', 'builtin/pack-objects.c', - 'builtin/pack-redundant.c', 'builtin/pack-refs.c', 'builtin/patch-id.c', 'builtin/prune-packed.c', @@ -608,14 +633,11 @@ builtin_sources = [ 'builtin/write-tree.c', ] -libgit_sources += custom_target( - input: 'command-list.txt', - output: 'command-list.h', - command: [shell, meson.current_source_dir() + '/generate-cmdlist.sh', meson.current_source_dir(), '@OUTPUT@'], - env: script_environment, -) +if not get_option('breaking_changes') + builtin_sources += 'builtin/pack-redundant.c' +endif -libgit_sources += custom_target( +builtin_sources += custom_target( output: 'config-list.h', command: [ shell, @@ -626,8 +648,8 @@ libgit_sources += custom_target( env: script_environment, ) -libgit_sources += custom_target( - input: 'Documentation/githooks.txt', +builtin_sources += custom_target( + input: 'Documentation/githooks.adoc', output: 'hook-list.h', command: [ shell, @@ -651,12 +673,13 @@ build_options_config.set('GIT_TEST_CMP_USE_COPIED_CONTEXT', '') build_options_config.set('GIT_TEST_INDEX_VERSION', '') build_options_config.set('GIT_TEST_OPTS', '') build_options_config.set('GIT_TEST_PERL_FATAL_WARNINGS', '') -build_options_config.set('GIT_TEST_UTF8_LOCALE', '') +build_options_config.set_quoted('GIT_TEST_UTF8_LOCALE', get_option('test_utf8_locale')) build_options_config.set_quoted('LOCALEDIR', fs.as_posix(get_option('prefix') / get_option('localedir'))) build_options_config.set('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb')) -if get_option('sane_tool_path') != '' - build_options_config.set_quoted('BROKEN_PATH_FIX', 's|^\# @BROKEN_PATH_FIX@$|git_broken_path_fix "' + get_option('sane_tool_path') + '"|') +if get_option('sane_tool_path').length() != 0 + sane_tool_path = (host_machine.system() == 'windows' ? ';' : ':').join(get_option('sane_tool_path')) + build_options_config.set_quoted('BROKEN_PATH_FIX', 's|^\# @BROKEN_PATH_FIX@$|git_broken_path_fix "' + sane_tool_path + '"|') else build_options_config.set_quoted('BROKEN_PATH_FIX', '/^\# @BROKEN_PATH_FIX@$/d') endif @@ -676,7 +699,6 @@ libgit_c_args = [ '-DETC_GITATTRIBUTES="' + get_option('gitattributes') + '"', '-DETC_GITCONFIG="' + get_option('gitconfig') + '"', '-DFALLBACK_RUNTIME_PREFIX="' + get_option('prefix') + '"', - '-DGIT_EXEC_PATH="' + get_option('prefix') / get_option('libexecdir') / 'git-core"', '-DGIT_HOST_CPU="' + host_machine.cpu_family() + '"', '-DGIT_HTML_PATH="' + get_option('datadir') / 'doc/git-doc"', '-DGIT_INFO_PATH="' + get_option('infodir') + '"', @@ -710,7 +732,6 @@ if get_option('warning_level') in ['2','3', 'everything'] and compiler.get_argum # These are disabled because we have these all over the place. '-Wno-empty-body', '-Wno-missing-field-initializers', - '-Wno-sign-compare', ] if compiler.has_argument(cflag) libgit_c_args += cflag @@ -718,6 +739,13 @@ if get_option('warning_level') in ['2','3', 'everything'] and compiler.get_argum endforeach endif +if get_option('breaking_changes') + build_options_config.set('WITH_BREAKING_CHANGES', 'YesPlease') + libgit_c_args += '-DWITH_BREAKING_CHANGES' +else + build_options_config.set('WITH_BREAKING_CHANGES', '') +endif + if get_option('b_sanitize').contains('address') build_options_config.set('SANITIZE_ADDRESS', 'YesCompiledWithIt') else @@ -751,13 +779,28 @@ endif # features. It is optional if you want to neither execute tests nor use any of # these optional features. perl_required = get_option('perl') -if get_option('tests') or get_option('gitweb').enabled() +if get_option('tests') or get_option('gitweb').enabled() or 'netrc' in get_option('credential_helpers') perl_required = true endif # Note that we only set NO_PERL if the Perl features were disabled by the user. # It may not be set when we have found Perl, but only use it to run tests. -perl = find_program('perl', version: '>=5.8.1', dirs: program_path, required: perl_required) +# +# At the time of writing, executing `perl --version` results in a string +# similar to the following output: +# +# This is perl 5, version 40, subversion 0 (v5.40.0) built for x86_64-linux-thread-multi +# +# Meson picks up the "40" as version number instead of using "v5.40.0" +# due to the regular expression it uses. This got fixed in Meson 1.7.0, +# but meanwhile we have to either use `-V:version` instead of `--version`, +# which we can do starting with Meson 1.5.0 and newer, or we have to +# match against the minor version. +if meson.version().version_compare('>=1.5.0') + perl = find_program('perl', dirs: program_path, required: perl_required, version: '>=5.26.0', version_argument: '-V:version') +else + perl = find_program('perl', dirs: program_path, required: perl_required, version: '>=26') +endif perl_features_enabled = perl.found() and get_option('perl').allowed() if perl_features_enabled build_options_config.set('NO_PERL', '') @@ -780,11 +823,23 @@ else build_options_config.set('NO_PERL_CPAN_FALLBACKS', '') endif -zlib = dependency('zlib', default_options: ['default_library=static', 'tests=disabled']) -if zlib.version().version_compare('<1.2.0') - libgit_c_args += '-DNO_DEFLATE_BOUND' +zlib_backend = get_option('zlib_backend') +if zlib_backend in ['auto', 'zlib-ng'] + zlib_ng = dependency('zlib-ng', required: zlib_backend == 'zlib-ng') + if zlib_ng.found() + zlib_backend = 'zlib-ng' + libgit_c_args += '-DHAVE_ZLIB_NG' + libgit_dependencies += zlib_ng + endif +endif +if zlib_backend in ['auto', 'zlib'] + zlib = dependency('zlib', default_options: ['default_library=static', 'tests=disabled']) + if zlib.version().version_compare('<1.2.0') + libgit_c_args += '-DNO_DEFLATE_BOUND' + endif + zlib_backend = 'zlib' + libgit_dependencies += zlib endif -libgit_dependencies += zlib threads = dependency('threads', required: false) if threads.found() @@ -915,7 +970,9 @@ if curl.found() use_curl_for_imap_send = true endif - libgit_dependencies += curl + # Most executables don't have to link against libcurl, but we still need its + # include directories so that we can resolve LIBCURL_VERSION in "help.c". + libgit_dependencies += curl.partial_dependency(includes: true) libgit_c_args += '-DCURL_DISABLE_TYPECHECK' build_options_config.set('NO_CURL', '') else @@ -1059,11 +1116,11 @@ elif host_machine.system() == 'windows' libgit_sources += [ 'compat/mingw.c', 'compat/winansi.c', + 'compat/win32/dirent.c', 'compat/win32/flush.c', 'compat/win32/path-utils.c', 'compat/win32/pthread.c', 'compat/win32/syslog.c', - 'compat/win32/dirent.c', 'compat/win32mmap.c', 'compat/nedmalloc/nedmalloc.c', ] @@ -1327,16 +1384,24 @@ if not meson.is_cross_build() and fs.exists('/dev/tty') libgit_c_args += '-DHAVE_DEV_TTY' endif +csprng_backend = get_option('csprng_backend') https_backend = get_option('https_backend') +sha1_backend = get_option('sha1_backend') +sha1_unsafe_backend = get_option('sha1_unsafe_backend') +sha256_backend = get_option('sha256_backend') -security_framework = dependency('Security', required: https_backend == 'CommonCrypto') +security_framework = dependency('Security', required: 'CommonCrypto' in [https_backend, sha1_backend, sha1_unsafe_backend]) core_foundation_framework = dependency('CoreFoundation', required: security_framework.found()) if https_backend == 'auto' and security_framework.found() https_backend = 'CommonCrypto' endif -openssl_required = https_backend == 'openssl' or get_option('sha1_backend') == 'openssl' or get_option('sha256_backend') == 'openssl' -openssl = dependency('openssl', required: openssl_required, default_options: ['default_library=static']) +openssl_required = 'openssl' in [csprng_backend, https_backend, sha1_backend, sha1_unsafe_backend, sha256_backend] +openssl = dependency('openssl', + required: openssl_required, + allow_fallback: openssl_required or https_backend == 'auto', + default_options: ['default_library=static'], +) if https_backend == 'auto' and openssl.found() https_backend = 'openssl' endif @@ -1350,13 +1415,13 @@ elif https_backend == 'openssl' else # We either couldn't find any dependencies with 'auto' or the user requested # 'none'. Both cases are benign. + https_backend = 'none' endif if https_backend != 'openssl' libgit_c_args += '-DNO_OPENSSL' endif -sha1_backend = get_option('sha1_backend') if sha1_backend == 'sha1dc' libgit_c_args += '-DSHA1_DC' libgit_c_args += '-DSHA1DC_NO_STANDARD_INCLUDES=1' @@ -1369,22 +1434,40 @@ if sha1_backend == 'sha1dc' 'sha1dc/sha1.c', 'sha1dc/ubc_check.c', ] -elif sha1_backend == 'common-crypto' +endif +if sha1_backend == 'CommonCrypto' or sha1_unsafe_backend == 'CommonCrypto' + if sha1_backend == 'CommonCrypto' + libgit_c_args += '-DSHA1_APPLE' + endif + if sha1_unsafe_backend == 'CommonCrypto' + libgit_c_args += '-DSHA1_APPLE_UNSAFE' + endif + libgit_c_args += '-DCOMMON_DIGEST_FOR_OPENSSL' - libgit_c_args += '-DSHA1_APPLE' # Apple CommonCrypto requires chunking libgit_c_args += '-DSHA1_MAX_BLOCK_SIZE=1024L*1024L*1024L' -elif sha1_backend == 'openssl' - libgit_c_args += '-DSHA1_OPENSSL' +endif +if sha1_backend == 'openssl' or sha1_unsafe_backend == 'openssl' + if sha1_backend == 'openssl' + libgit_c_args += '-DSHA1_OPENSSL' + endif + if sha1_unsafe_backend == 'openssl' + libgit_c_args += '-DSHA1_OPENSSL_UNSAFE' + endif + libgit_dependencies += openssl -elif sha1_backend == 'block' - libgit_c_args += '-DSHA1_BLK' +endif +if sha1_backend == 'block' or sha1_unsafe_backend == 'block' + if sha1_backend == 'block' + libgit_c_args += '-DSHA1_BLK' + endif + if sha1_unsafe_backend == 'block' + libgit_c_args += '-DSHA1_BLK_UNSAFE' + endif + libgit_sources += 'block-sha1/sha1.c' -else - error('Unhandled SHA1 backend ' + sha1_backend) endif -sha256_backend = get_option('sha256_backend') if sha256_backend == 'openssl' libgit_c_args += '-DSHA256_OPENSSL' libgit_dependencies += openssl @@ -1403,23 +1486,36 @@ else error('Unhandled SHA256 backend ' + sha256_backend) endif -if compiler.has_header_symbol('stdlib.h', 'arc4random_buf') +# Backends are ordered to reflect our preference for more secure and faster +# ones over the ones that are less so. +if csprng_backend in ['auto', 'arc4random'] and compiler.has_header_symbol('stdlib.h', 'arc4random_buf', required: csprng_backend == 'arc4random') libgit_c_args += '-DHAVE_ARC4RANDOM' -elif compiler.has_header_symbol('bsd/stdlib.h', 'arc4random_buf') + csprng_backend = 'arc4random' +elif csprng_backend in ['auto', 'arc4random_bsd'] and compiler.has_header_symbol('bsd/stdlib.h', 'arc4random_buf', required: csprng_backend == 'arc4random_bsd') libgit_c_args += '-DHAVE_ARC4RANDOM_BSD' -elif compiler.has_function('getrandom', prefix: '#include <sys/random.h>') + csprng_backend = 'arc4random_bsd' +elif csprng_backend in ['auto', 'getrandom'] and compiler.has_header_symbol('sys/random.h', 'getrandom', required: csprng_backend == 'getrandom') libgit_c_args += '-DHAVE_GETRANDOM' -elif compiler.has_function('getentropy', prefix: '#include <unistd.h>') + csprng_backend = 'getrandom' +elif csprng_backend in ['auto', 'getentropy'] and compiler.has_header_symbol('unistd.h', 'getentropy', required: csprng_backend == 'getentropy') libgit_c_args += '-DHAVE_GETENTROPY' -elif compiler.has_function('RtlGenRandom', prefix: '#include <windows.h>\n#include <ntsecapi.h>') + csprng_backend = 'getentropy' +elif csprng_backend in ['auto', 'rtlgenrandom'] and compiler.has_header_symbol('ntsecapi.h', 'RtlGenRandom', prefix: '#include <windows.h>', required: csprng_backend == 'rtlgenrandom') libgit_c_args += '-DHAVE_RTLGENRANDOM' -elif openssl.found() + csprng_backend = 'rtlgenrandom' +elif csprng_backend in ['auto', 'openssl'] and openssl.found() libgit_c_args += '-DHAVE_OPENSSL_CSPRNG' + csprng_backend = 'openssl' +elif csprng_backend in ['auto', 'urandom'] + csprng_backend = 'urandom' +else + error('Unsupported CSPRNG backend: ' + csprng_backend) endif if get_option('runtime_prefix') libgit_c_args += '-DRUNTIME_PREFIX' build_options_config.set('RUNTIME_PREFIX', 'true') + git_exec_path = get_option('libexecdir') / 'git-core' if compiler.has_header('mach-o/dyld.h') libgit_c_args += '-DHAVE_NS_GET_EXECUTABLE_PATH' @@ -1456,7 +1552,9 @@ if get_option('runtime_prefix') endif else build_options_config.set('RUNTIME_PREFIX', 'false') + git_exec_path = get_option('prefix') / get_option('libexecdir') / 'git-core' endif +libgit_c_args += '-DGIT_EXEC_PATH="' + git_exec_path + '"' git_version_file = custom_target( command: [ @@ -1487,30 +1585,18 @@ version_def_h = custom_target( depends: [git_version_file], env: version_gen_environment, ) - -# Build a separate library for "version.c" so that we do not have to rebuild -# everything when the current Git commit changes. -libgit_version_library = static_library('git-version', - sources: [ - 'version.c', - version_def_h, - ], - c_args: libgit_c_args, - dependencies: libgit_dependencies, - include_directories: libgit_include_directories, -) - -libgit_library = static_library('git', - sources: libgit_sources, - c_args: libgit_c_args, - link_with: libgit_version_library, - dependencies: libgit_dependencies, - include_directories: libgit_include_directories, -) +libgit_sources += version_def_h libgit = declare_dependency( + link_with: static_library('git', + sources: libgit_sources, + c_args: libgit_c_args + [ + '-DGIT_VERSION_H="' + version_def_h.full_path() + '"', + ], + dependencies: libgit_dependencies, + include_directories: libgit_include_directories, + ), compile_args: libgit_c_args, - link_with: libgit_library, dependencies: libgit_dependencies, include_directories: libgit_include_directories, ) @@ -1551,88 +1637,89 @@ if host_machine.system() == 'windows' error('Unsupported compiler ' + compiler.get_id()) endif endif -common_main_library = static_library('common-main', - sources: common_main_sources, - c_args: libgit_c_args, - dependencies: libgit_dependencies, - include_directories: libgit_include_directories, -) -common_main = declare_dependency( - link_with: common_main_library, + +libgit_commonmain = declare_dependency( + link_with: static_library('common-main', + sources: common_main_sources, + dependencies: [ libgit ], + ), link_args: common_main_link_args, + dependencies: [ libgit ], ) bin_wrappers = [ ] test_dependencies = [ ] -git = executable('git', +git_builtin = executable('git', sources: builtin_sources + 'git.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', ) -bin_wrappers += git +bin_wrappers += git_builtin test_dependencies += executable('git-daemon', sources: 'daemon.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', ) test_dependencies += executable('git-sh-i18n--envsubst', sources: 'sh-i18n--envsubst.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', ) bin_wrappers += executable('git-shell', sources: 'shell.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', ) test_dependencies += executable('git-http-backend', sources: 'http-backend.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', ) bin_wrappers += executable('scalar', sources: 'scalar.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', ) if get_option('curl').enabled() - curl_sources = [ - 'http.c', - 'http-walker.c', - ] + libgit_curl = declare_dependency( + sources: [ + 'http.c', + 'http-walker.c', + ], + dependencies: [libgit_commonmain, curl], + ) - git_remote_http = executable('git-remote-http', - sources: curl_sources + 'remote-curl.c', - dependencies: [libgit, common_main], + test_dependencies += executable('git-remote-http', + sources: 'remote-curl.c', + dependencies: [libgit_curl], install: true, install_dir: get_option('libexecdir') / 'git-core', ) - test_dependencies += git_remote_http test_dependencies += executable('git-http-fetch', - sources: curl_sources + 'http-fetch.c', - dependencies: [libgit, common_main], + sources: 'http-fetch.c', + dependencies: [libgit_curl], install: true, install_dir: get_option('libexecdir') / 'git-core', ) if expat.found() test_dependencies += executable('git-http-push', - sources: curl_sources + 'http-push.c', - dependencies: [libgit, common_main], + sources: 'http-push.c', + dependencies: [libgit_curl], install: true, install_dir: get_option('libexecdir') / 'git-core', ) @@ -1640,8 +1727,8 @@ if get_option('curl').enabled() foreach alias : [ 'git-remote-https', 'git-remote-ftp', 'git-remote-ftps' ] test_dependencies += executable(alias, - objects: git_remote_http.extract_all_objects(recursive: false), - dependencies: [libgit, common_main], + sources: 'remote-curl.c', + dependencies: [libgit_curl], ) install_symlink(alias + executable_suffix, @@ -1651,22 +1738,17 @@ if get_option('curl').enabled() endforeach endif -imap_send_sources = ['imap-send.c'] -if use_curl_for_imap_send - imap_send_sources += curl_sources -endif - test_dependencies += executable('git-imap-send', - sources: imap_send_sources, - dependencies: [libgit, common_main], + sources: 'imap-send.c', + dependencies: [ use_curl_for_imap_send ? libgit_curl : libgit_commonmain ], install: true, install_dir: get_option('libexecdir') / 'git-core', ) foreach alias : [ 'git-receive-pack', 'git-upload-archive', 'git-upload-pack' ] bin_wrappers += executable(alias, - objects: git.extract_all_objects(recursive: false), - dependencies: [libgit, common_main], + objects: git_builtin.extract_all_objects(recursive: false), + dependencies: [libgit_commonmain], ) install_symlink(alias + executable_suffix, @@ -1859,7 +1941,6 @@ endforeach if intl.found() subdir('po') endif -subdir('contrib') # Gitweb requires Perl, so we disable the auto-feature if Perl was not found. # We make sure further up that Perl is required in case the gitweb option is @@ -1881,17 +1962,22 @@ if get_option('tests') subdir('t') endif +if get_option('fuzzers') + subdir('oss-fuzz') +endif + subdir('bin-wrappers') if get_option('docs') != [] subdir('Documentation') endif +subdir('contrib') + foreach key, value : { 'DIFF': diff.full_path(), + 'GIT_SOURCE_DIR': meson.project_source_root(), 'GIT_TEST_CMP': diff.full_path() + ' -u', 'GIT_TEST_GITPERLLIB': meson.project_build_root() / 'perl', - 'GIT_TEST_MERGE_TOOLS_DIR': meson.project_source_root() / 'mergetools', - 'GIT_TEST_POPATH': meson.project_source_root() / 'po', 'GIT_TEST_TEMPLATE_DIR': meson.project_build_root() / 'templates', 'GIT_TEST_TEXTDOMAINDIR': meson.project_build_root() / 'po', 'PAGER_ENV': get_option('pager_environment'), @@ -1914,6 +2000,27 @@ configure_file( configuration: build_options_config, ) +# Development environments can be used via `meson devenv -C <builddir>`. This +# allows you to execute test scripts directly with the built Git version and +# puts the built version of Git in your PATH. +devenv = environment() +devenv.set('GIT_BUILD_DIR', meson.current_build_dir()) +devenv.prepend('PATH', meson.current_build_dir() / 'bin-wrappers') +meson.add_devenv(devenv) + +# Generate the 'version' file in the distribution tarball. This is used via +# `meson dist -C <builddir>` to populate the source archive with the Git +# version that the archive is being generated from. +meson.add_dist_script( + shell, + '-c', + '"$1" "$2" "$3" --format="@GIT_VERSION@" "$MESON_DIST_ROOT/version"', + 'GIT-VERSION-GEN', + shell, + meson.current_source_dir() / 'GIT-VERSION-GEN', + meson.current_source_dir(), +) + summary({ 'curl': curl.found(), 'expat': expat.found(), @@ -1925,3 +2032,12 @@ summary({ 'perl': perl_features_enabled, 'python': python.found(), }, section: 'Auto-detected features') + +summary({ + 'csprng': csprng_backend, + 'https': https_backend, + 'sha1': sha1_backend, + 'sha1_unsafe': sha1_unsafe_backend, + 'sha256': sha256_backend, + 'zlib': zlib_backend, +}, section: 'Backends') diff --git a/meson_options.txt b/meson_options.txt index f50bb40cdf..78d172a740 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -13,8 +13,8 @@ option('perl_cpan_fallback', type: 'boolean', value: true, description: 'Install bundled copies of CPAN modules that serve as a fallback in case the modules are not available on the system.') option('runtime_prefix', type: 'boolean', value: false, description: 'Resolve ancillary tooling and support files relative to the location of the runtime binary instead of hard-coding them into the binary.') -option('sane_tool_path', type: 'string', value: '', - description: 'A colon-separated list of paths to prepend to PATH if your tools in /usr/bin are broken.') +option('sane_tool_path', type: 'array', value: [], + description: 'An array of paths to pick up tools from in case the normal tools are broken or lacking.') # Build information compiled into Git and other parts like documentation. option('build_date', type: 'string', value: '', @@ -27,6 +27,10 @@ option('version', type: 'string', value: '', description: 'Version string reported by git-version(1) and other tools.') # Features supported by Git. +option('contrib', type: 'array', value: [ 'completion' ], choices: [ 'completion', 'contacts', 'subtree' ], + description: 'Contributed features to include.') +option('credential_helpers', type: 'array', value: [ ], choices: [ 'libsecret', 'netrc', 'osxkeychain', 'wincred' ], + description: 'Contributed features to include.') option('curl', type: 'feature', value: 'enabled', description: 'Build helpers used to access remotes with the HTTP transport.') option('expat', type: 'feature', value: 'enabled', @@ -47,14 +51,22 @@ option('regex', type: 'feature', value: 'auto', description: 'Use the system-provided regex library instead of the bundled one.') # Backends. +option('csprng_backend', type: 'combo', value: 'auto', choices: ['auto', 'arc4random', 'arc4random_bsd', 'getrandom', 'getentropy', 'rtlgenrandom', 'openssl', 'urandom'], + description: 'The backend to use for generating cryptographically-secure pseudo-random numbers.') option('https_backend', type: 'combo', value: 'auto', choices: ['auto', 'openssl', 'CommonCrypto', 'none'], description: 'The HTTPS backend to use when connecting to remotes.') -option('sha1_backend', type: 'combo', choices: ['openssl', 'block', 'sha1dc', 'common-crypto'], value: 'sha1dc', - description: 'The backend used for hashing objects with the SHA1 object format') +option('sha1_backend', type: 'combo', choices: ['openssl', 'block', 'sha1dc', 'CommonCrypto'], value: 'sha1dc', + description: 'The backend used for hashing objects with the SHA1 object format.') +option('sha1_unsafe_backend', type: 'combo', choices: ['openssl', 'block', 'CommonCrypto', 'none'], value: 'none', + description: 'The backend used for hashing data with the SHA1 object format in case no cryptographic security is needed.') option('sha256_backend', type: 'combo', choices: ['openssl', 'nettle', 'gcrypt', 'block'], value: 'block', - description: 'The backend used for hashing objects with the SHA256 object format') + description: 'The backend used for hashing objects with the SHA256 object format.') +option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], value: 'auto', + description: 'The backend used for compressing objects and other data.') # Build tweaks. +option('breaking_changes', type: 'boolean', value: false, + description: 'Enable upcoming breaking changes.') option('macos_use_homebrew_gettext', type: 'boolean', value: true, description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.') @@ -89,7 +101,13 @@ option('docs_backend', type: 'combo', choices: ['asciidoc', 'asciidoctor', 'auto description: 'Which backend to use to generate documentation.') # Testing. +option('coccinelle', type: 'feature', value: 'auto', + description: 'Provide a coccicheck target that generates a Coccinelle patch.') option('tests', type: 'boolean', value: true, description: 'Enable building tests. This requires Perl, but is separate from the "perl" option such that you can build tests without Perl features enabled.') option('test_output_directory', type: 'string', description: 'Path to the directory used to store test outputs') +option('test_utf8_locale', type: 'string', + description: 'Name of a UTF-8 locale used for testing.') +option('fuzzers', type: 'boolean', value: false, + description: 'Enable building fuzzers.') diff --git a/midx-write.c b/midx-write.c index 0066594fa6..48d6558253 100644 --- a/midx-write.c +++ b/midx-write.c @@ -658,8 +658,8 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash, strbuf_addf(&buf, "%s-%s.rev", midx_name, hash_to_hex_algop(midx_hash, ctx->repo->hash_algo)); - tmp_file = write_rev_file_order(NULL, ctx->pack_order, ctx->entries_nr, - midx_hash, WRITE_REV); + tmp_file = write_rev_file_order(ctx->repo->hash_algo, NULL, ctx->pack_order, + ctx->entries_nr, midx_hash, WRITE_REV); if (finalize_object_file(tmp_file, buf.buf)) die(_("cannot store reverse index file")); @@ -1131,7 +1131,8 @@ static int write_midx_internal(struct repository *r, const char *object_dir, ctx.pack_paths_checked = 0; if (flags & MIDX_PROGRESS) - ctx.progress = start_delayed_progress(_("Adding packfiles to multi-pack-index"), 0); + ctx.progress = start_delayed_progress(r, + _("Adding packfiles to multi-pack-index"), 0); else ctx.progress = NULL; @@ -1335,7 +1336,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir, return -1; } - if (adjust_shared_perm(get_tempfile_path(incr))) { + if (adjust_shared_perm(r, get_tempfile_path(incr))) { error(_("unable to adjust shared permissions for '%s'"), get_tempfile_path(incr)); return -1; @@ -1539,7 +1540,9 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla CALLOC_ARRAY(count, m->num_packs); if (flags & MIDX_PROGRESS) - progress = start_delayed_progress(_("Counting referenced objects"), + progress = start_delayed_progress( + r, + _("Counting referenced objects"), m->num_objects); for (i = 0; i < m->num_objects; i++) { int pack_int_id = nth_midxed_pack_int_id(m, i); @@ -1549,7 +1552,9 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla stop_progress(&progress); if (flags & MIDX_PROGRESS) - progress = start_delayed_progress(_("Finding and deleting unreferenced packfiles"), + progress = start_delayed_progress( + r, + _("Finding and deleting unreferenced packfiles"), m->num_packs); for (i = 0; i < m->num_packs; i++) { char *pack_name; @@ -907,7 +907,8 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag midx_report(_("incorrect checksum")); if (flags & MIDX_PROGRESS) - progress = start_delayed_progress(_("Looking for referenced packfiles"), + progress = start_delayed_progress(r, + _("Looking for referenced packfiles"), m->num_packs + m->num_packs_in_base); for (i = 0; i < m->num_packs + m->num_packs_in_base; i++) { if (prepare_midx_pack(r, m, i)) @@ -927,7 +928,8 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag } if (flags & MIDX_PROGRESS) - progress = start_sparse_progress(_("Verifying OID order in multi-pack-index"), + progress = start_sparse_progress(r, + _("Verifying OID order in multi-pack-index"), m->num_objects - 1); for (curr = m; curr; curr = curr->base_midx) { @@ -959,14 +961,17 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag } if (flags & MIDX_PROGRESS) - progress = start_sparse_progress(_("Sorting objects by packfile"), + progress = start_sparse_progress(r, + _("Sorting objects by packfile"), m->num_objects); display_progress(progress, 0); /* TODO: Measure QSORT() progress */ QSORT(pairs, m->num_objects, compare_pair_pos_vs_id); stop_progress(&progress); if (flags & MIDX_PROGRESS) - progress = start_sparse_progress(_("Verifying object offsets"), m->num_objects); + progress = start_sparse_progress(r, + _("Verifying object offsets"), + m->num_objects); for (i = 0; i < m->num_objects + m->num_objects_in_base; i++) { struct object_id oid; struct pack_entry e; diff --git a/notes-merge.c b/notes-merge.c index 8d701ed428..67a472020d 100644 --- a/notes-merge.c +++ b/notes-merge.c @@ -275,41 +275,45 @@ static void diff_tree_local(struct notes_merge_options *o, static void check_notes_merge_worktree(struct notes_merge_options *o) { + struct strbuf buf = STRBUF_INIT; + if (!o->has_worktree) { /* * Must establish NOTES_MERGE_WORKTREE. * Abort if NOTES_MERGE_WORKTREE already exists */ - if (file_exists(git_path(NOTES_MERGE_WORKTREE)) && - !is_empty_dir(git_path(NOTES_MERGE_WORKTREE))) { + if (file_exists(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE)) && + !is_empty_dir(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE))) { if (advice_enabled(ADVICE_RESOLVE_CONFLICT)) die(_("You have not concluded your previous " "notes merge (%s exists).\nPlease, use " "'git notes merge --commit' or 'git notes " "merge --abort' to commit/abort the " "previous merge before you start a new " - "notes merge."), git_path("NOTES_MERGE_*")); + "notes merge."), repo_git_path_replace(the_repository, &buf, "NOTES_MERGE_*")); else die(_("You have not concluded your notes merge " - "(%s exists)."), git_path("NOTES_MERGE_*")); + "(%s exists)."), repo_git_path_replace(the_repository, &buf, "NOTES_MERGE_*")); } - if (safe_create_leading_directories_const(git_path( + if (safe_create_leading_directories_const(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE "/.test"))) die_errno("unable to create directory %s", - git_path(NOTES_MERGE_WORKTREE)); + repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE)); o->has_worktree = 1; - } else if (!file_exists(git_path(NOTES_MERGE_WORKTREE))) + } else if (!file_exists(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE))) /* NOTES_MERGE_WORKTREE should already be established */ die("missing '%s'. This should not happen", - git_path(NOTES_MERGE_WORKTREE)); + repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE)); + + strbuf_release(&buf); } static void write_buf_to_worktree(const struct object_id *obj, const char *buf, unsigned long size) { int fd; - char *path = git_pathdup(NOTES_MERGE_WORKTREE "/%s", oid_to_hex(obj)); + char *path = repo_git_path(the_repository, NOTES_MERGE_WORKTREE "/%s", oid_to_hex(obj)); if (safe_create_leading_directories_const(path)) die_errno("unable to create directory for '%s'", path); @@ -695,7 +699,7 @@ int notes_merge_commit(struct notes_merge_options *o, const char *msg = strstr(buffer, "\n\n"); int baselen; - git_path_buf(&path, NOTES_MERGE_WORKTREE); + repo_git_path_replace(the_repository, &path, NOTES_MERGE_WORKTREE); if (o->verbosity >= 3) printf("Committing notes in notes merge worktree at %s\n", path.buf); @@ -757,7 +761,7 @@ int notes_merge_abort(struct notes_merge_options *o) struct strbuf buf = STRBUF_INIT; int ret; - git_path_buf(&buf, NOTES_MERGE_WORKTREE); + repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE); if (o->verbosity >= 3) printf("Removing notes merge worktree at %s/*\n", buf.buf); ret = remove_dir_recursively(&buf, REMOVE_DIR_KEEP_TOPLEVEL); diff --git a/object-file.c b/object-file.c index 5b792b3dd4..726e41a047 100644 --- a/object-file.c +++ b/object-file.c @@ -86,84 +86,90 @@ static const struct object_id null_oid_sha256 = { .algo = GIT_HASH_SHA256, }; -static void git_hash_sha1_init(git_hash_ctx *ctx) +static void git_hash_sha1_init(struct git_hash_ctx *ctx) { - git_SHA1_Init(&ctx->sha1); + ctx->algop = &hash_algos[GIT_HASH_SHA1]; + git_SHA1_Init(&ctx->state.sha1); } -static void git_hash_sha1_clone(git_hash_ctx *dst, const git_hash_ctx *src) +static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src) { - git_SHA1_Clone(&dst->sha1, &src->sha1); + dst->algop = src->algop; + git_SHA1_Clone(&dst->state.sha1, &src->state.sha1); } -static void git_hash_sha1_update(git_hash_ctx *ctx, const void *data, size_t len) +static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len) { - git_SHA1_Update(&ctx->sha1, data, len); + git_SHA1_Update(&ctx->state.sha1, data, len); } -static void git_hash_sha1_final(unsigned char *hash, git_hash_ctx *ctx) +static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx) { - git_SHA1_Final(hash, &ctx->sha1); + git_SHA1_Final(hash, &ctx->state.sha1); } -static void git_hash_sha1_final_oid(struct object_id *oid, git_hash_ctx *ctx) +static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx) { - git_SHA1_Final(oid->hash, &ctx->sha1); + git_SHA1_Final(oid->hash, &ctx->state.sha1); memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ); oid->algo = GIT_HASH_SHA1; } -static void git_hash_sha1_init_unsafe(git_hash_ctx *ctx) +static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx) { - git_SHA1_Init_unsafe(&ctx->sha1_unsafe); + ctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]); + git_SHA1_Init_unsafe(&ctx->state.sha1_unsafe); } -static void git_hash_sha1_clone_unsafe(git_hash_ctx *dst, const git_hash_ctx *src) +static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src) { - git_SHA1_Clone_unsafe(&dst->sha1_unsafe, &src->sha1_unsafe); + dst->algop = src->algop; + git_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe); } -static void git_hash_sha1_update_unsafe(git_hash_ctx *ctx, const void *data, +static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data, size_t len) { - git_SHA1_Update_unsafe(&ctx->sha1_unsafe, data, len); + git_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len); } -static void git_hash_sha1_final_unsafe(unsigned char *hash, git_hash_ctx *ctx) +static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx) { - git_SHA1_Final_unsafe(hash, &ctx->sha1_unsafe); + git_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe); } -static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, git_hash_ctx *ctx) +static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx) { - git_SHA1_Final_unsafe(oid->hash, &ctx->sha1_unsafe); + git_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe); memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ); oid->algo = GIT_HASH_SHA1; } -static void git_hash_sha256_init(git_hash_ctx *ctx) +static void git_hash_sha256_init(struct git_hash_ctx *ctx) { - git_SHA256_Init(&ctx->sha256); + ctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]); + git_SHA256_Init(&ctx->state.sha256); } -static void git_hash_sha256_clone(git_hash_ctx *dst, const git_hash_ctx *src) +static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src) { - git_SHA256_Clone(&dst->sha256, &src->sha256); + dst->algop = src->algop; + git_SHA256_Clone(&dst->state.sha256, &src->state.sha256); } -static void git_hash_sha256_update(git_hash_ctx *ctx, const void *data, size_t len) +static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len) { - git_SHA256_Update(&ctx->sha256, data, len); + git_SHA256_Update(&ctx->state.sha256, data, len); } -static void git_hash_sha256_final(unsigned char *hash, git_hash_ctx *ctx) +static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx) { - git_SHA256_Final(hash, &ctx->sha256); + git_SHA256_Final(hash, &ctx->state.sha256); } -static void git_hash_sha256_final_oid(struct object_id *oid, git_hash_ctx *ctx) +static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx) { - git_SHA256_Final(oid->hash, &ctx->sha256); + git_SHA256_Final(oid->hash, &ctx->state.sha256); /* * This currently does nothing, so the compiler should optimize it out, * but keep it in case we extend the hash size again. @@ -172,18 +178,18 @@ static void git_hash_sha256_final_oid(struct object_id *oid, git_hash_ctx *ctx) oid->algo = GIT_HASH_SHA256; } -static void git_hash_unknown_init(git_hash_ctx *ctx UNUSED) +static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED) { BUG("trying to init unknown hash"); } -static void git_hash_unknown_clone(git_hash_ctx *dst UNUSED, - const git_hash_ctx *src UNUSED) +static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED, + const struct git_hash_ctx *src UNUSED) { BUG("trying to clone unknown hash"); } -static void git_hash_unknown_update(git_hash_ctx *ctx UNUSED, +static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED, const void *data UNUSED, size_t len UNUSED) { @@ -191,17 +197,33 @@ static void git_hash_unknown_update(git_hash_ctx *ctx UNUSED, } static void git_hash_unknown_final(unsigned char *hash UNUSED, - git_hash_ctx *ctx UNUSED) + struct git_hash_ctx *ctx UNUSED) { BUG("trying to finalize unknown hash"); } static void git_hash_unknown_final_oid(struct object_id *oid UNUSED, - git_hash_ctx *ctx UNUSED) + struct git_hash_ctx *ctx UNUSED) { BUG("trying to finalize unknown hash"); } +static const struct git_hash_algo sha1_unsafe_algo = { + .name = "sha1", + .format_id = GIT_SHA1_FORMAT_ID, + .rawsz = GIT_SHA1_RAWSZ, + .hexsz = GIT_SHA1_HEXSZ, + .blksz = GIT_SHA1_BLKSZ, + .init_fn = git_hash_sha1_init_unsafe, + .clone_fn = git_hash_sha1_clone_unsafe, + .update_fn = git_hash_sha1_update_unsafe, + .final_fn = git_hash_sha1_final_unsafe, + .final_oid_fn = git_hash_sha1_final_oid_unsafe, + .empty_tree = &empty_tree_oid, + .empty_blob = &empty_blob_oid, + .null_oid = &null_oid_sha1, +}; + const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { { .name = NULL, @@ -214,11 +236,6 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { .update_fn = git_hash_unknown_update, .final_fn = git_hash_unknown_final, .final_oid_fn = git_hash_unknown_final_oid, - .unsafe_init_fn = git_hash_unknown_init, - .unsafe_clone_fn = git_hash_unknown_clone, - .unsafe_update_fn = git_hash_unknown_update, - .unsafe_final_fn = git_hash_unknown_final, - .unsafe_final_oid_fn = git_hash_unknown_final_oid, .empty_tree = NULL, .empty_blob = NULL, .null_oid = NULL, @@ -234,11 +251,7 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { .update_fn = git_hash_sha1_update, .final_fn = git_hash_sha1_final, .final_oid_fn = git_hash_sha1_final_oid, - .unsafe_init_fn = git_hash_sha1_init_unsafe, - .unsafe_clone_fn = git_hash_sha1_clone_unsafe, - .unsafe_update_fn = git_hash_sha1_update_unsafe, - .unsafe_final_fn = git_hash_sha1_final_unsafe, - .unsafe_final_oid_fn = git_hash_sha1_final_oid_unsafe, + .unsafe = &sha1_unsafe_algo, .empty_tree = &empty_tree_oid, .empty_blob = &empty_blob_oid, .null_oid = &null_oid_sha1, @@ -254,11 +267,6 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { .update_fn = git_hash_sha256_update, .final_fn = git_hash_sha256_final, .final_oid_fn = git_hash_sha256_final_oid, - .unsafe_init_fn = git_hash_sha256_init, - .unsafe_clone_fn = git_hash_sha256_clone, - .unsafe_update_fn = git_hash_sha256_update, - .unsafe_final_fn = git_hash_sha256_final, - .unsafe_final_oid_fn = git_hash_sha256_final_oid, .empty_tree = &empty_tree_oid_sha256, .empty_blob = &empty_blob_oid_sha256, .null_oid = &null_oid_sha256, @@ -305,6 +313,15 @@ int hash_algo_by_length(int len) return GIT_HASH_UNKNOWN; } +const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop) +{ + /* If we have a faster "unsafe" implementation, use that. */ + if (algop->unsafe) + return algop->unsafe; + /* Otherwise use the default one. */ + return algop; +} + /* * This is meant to hold a *small* number of objects that you would * want repo_read_object_file() to be able to return, but yet you do not want @@ -377,7 +394,7 @@ int mkdir_in_gitdir(const char *path) } strbuf_release(&sb); } - return adjust_shared_perm(path); + return adjust_shared_perm(the_repository, path); } static enum scld_error safe_create_leading_directories_1(char *path, int share) @@ -426,7 +443,7 @@ static enum scld_error safe_create_leading_directories_1(char *path, int share) ret = SCLD_VANISHED; else ret = SCLD_FAILED; - } else if (share && adjust_shared_perm(path)) { + } else if (share && adjust_shared_perm(the_repository, path)) { ret = SCLD_PERMS; } *slash = slash_character; @@ -465,14 +482,14 @@ int odb_mkstemp(struct strbuf *temp_filename, const char *pattern) * restrictive except to remove write permission. */ int mode = 0444; - git_path_buf(temp_filename, "objects/%s", pattern); + repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern); fd = git_mkstemp_mode(temp_filename->buf, mode); if (0 <= fd) return fd; /* slow path */ /* some mkstemp implementations erase temp_filename on failure */ - git_path_buf(temp_filename, "objects/%s", pattern); + repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern); safe_create_leading_directories(temp_filename->buf); return xmkstemp_mode(temp_filename->buf, mode); } @@ -706,7 +723,7 @@ static void read_info_alternates(struct repository *r, void add_to_alternates_file(const char *reference) { struct lock_file lock = LOCK_INIT; - char *alts = git_pathdup("objects/info/alternates"); + char *alts = repo_git_path(the_repository, "objects/info/alternates"); FILE *in, *out; int found = 0; @@ -1169,7 +1186,7 @@ int stream_object_signature(struct repository *r, const struct object_id *oid) unsigned long size; enum object_type obj_type; struct git_istream *st; - git_hash_ctx c; + struct git_hash_ctx c; char hdr[MAX_HEADER_LEN]; int hdrlen; @@ -1182,7 +1199,7 @@ int stream_object_signature(struct repository *r, const struct object_id *oid) /* Sha1.. */ r->hash_algo->init_fn(&c); - r->hash_algo->update_fn(&c, hdr, hdrlen); + git_hash_update(&c, hdr, hdrlen); for (;;) { char buf[1024 * 16]; ssize_t readlen = read_istream(st, buf, sizeof(buf)); @@ -1193,9 +1210,9 @@ int stream_object_signature(struct repository *r, const struct object_id *oid) } if (!readlen) break; - r->hash_algo->update_fn(&c, buf, readlen); + git_hash_update(&c, buf, readlen); } - r->hash_algo->final_oid_fn(&real_oid, &c); + git_hash_final_oid(&real_oid, &c); close_istream(st); return !oideq(oid, &real_oid) ? -1 : 0; } @@ -1934,15 +1951,15 @@ void *read_object_with_reference(struct repository *r, } } -static void hash_object_body(const struct git_hash_algo *algo, git_hash_ctx *c, +static void hash_object_body(const struct git_hash_algo *algo, struct git_hash_ctx *c, const void *buf, unsigned long len, struct object_id *oid, char *hdr, int *hdrlen) { algo->init_fn(c); - algo->update_fn(c, hdr, *hdrlen); - algo->update_fn(c, buf, len); - algo->final_oid_fn(oid, c); + git_hash_update(c, hdr, *hdrlen); + git_hash_update(c, buf, len); + git_hash_final_oid(oid, c); } static void write_object_file_prepare(const struct git_hash_algo *algo, @@ -1950,7 +1967,7 @@ static void write_object_file_prepare(const struct git_hash_algo *algo, enum object_type type, struct object_id *oid, char *hdr, int *hdrlen) { - git_hash_ctx c; + struct git_hash_ctx c; /* Generate the header */ *hdrlen = format_object_header(hdr, *hdrlen, type, len); @@ -1964,60 +1981,65 @@ static void write_object_file_prepare_literally(const struct git_hash_algo *algo const char *type, struct object_id *oid, char *hdr, int *hdrlen) { - git_hash_ctx c; + struct git_hash_ctx c; *hdrlen = format_object_header_literally(hdr, *hdrlen, type, len); hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen); } -static int check_collision(const char *filename_a, const char *filename_b) +#define CHECK_COLLISION_DEST_VANISHED -2 + +static int check_collision(const char *source, const char *dest) { - char buf_a[4096], buf_b[4096]; - int fd_a = -1, fd_b = -1; + char buf_source[4096], buf_dest[4096]; + int fd_source = -1, fd_dest = -1; int ret = 0; - fd_a = open(filename_a, O_RDONLY); - if (fd_a < 0) { - ret = error_errno(_("unable to open %s"), filename_a); + fd_source = open(source, O_RDONLY); + if (fd_source < 0) { + ret = error_errno(_("unable to open %s"), source); goto out; } - fd_b = open(filename_b, O_RDONLY); - if (fd_b < 0) { - ret = error_errno(_("unable to open %s"), filename_b); + fd_dest = open(dest, O_RDONLY); + if (fd_dest < 0) { + if (errno != ENOENT) + ret = error_errno(_("unable to open %s"), dest); + else + ret = CHECK_COLLISION_DEST_VANISHED; goto out; } while (1) { ssize_t sz_a, sz_b; - sz_a = read_in_full(fd_a, buf_a, sizeof(buf_a)); + sz_a = read_in_full(fd_source, buf_source, sizeof(buf_source)); if (sz_a < 0) { - ret = error_errno(_("unable to read %s"), filename_a); + ret = error_errno(_("unable to read %s"), source); goto out; } - sz_b = read_in_full(fd_b, buf_b, sizeof(buf_b)); + sz_b = read_in_full(fd_dest, buf_dest, sizeof(buf_dest)); if (sz_b < 0) { - ret = error_errno(_("unable to read %s"), filename_b); + ret = error_errno(_("unable to read %s"), dest); goto out; } - if (sz_a != sz_b || memcmp(buf_a, buf_b, sz_a)) { + if (sz_a != sz_b || memcmp(buf_source, buf_dest, sz_a)) { ret = error(_("files '%s' and '%s' differ in contents"), - filename_a, filename_b); + source, dest); goto out; } - if (sz_a < sizeof(buf_a)) + if (sz_a < sizeof(buf_source)) break; } out: - if (fd_a > -1) - close(fd_a); - if (fd_b > -1) - close(fd_b); + if (fd_source > -1) + close(fd_source); + if (fd_dest > -1) + close(fd_dest); return ret; } @@ -2032,8 +2054,11 @@ int finalize_object_file(const char *tmpfile, const char *filename) int finalize_object_file_flags(const char *tmpfile, const char *filename, enum finalize_object_file_flags flags) { - struct stat st; - int ret = 0; + unsigned retries = 0; + int ret; + +retry: + ret = 0; if (object_creation_mode == OBJECT_CREATION_USES_RENAMES) goto try_rename; @@ -2054,6 +2079,8 @@ int finalize_object_file_flags(const char *tmpfile, const char *filename, * left to unlink. */ if (ret && ret != EEXIST) { + struct stat st; + try_rename: if (!stat(filename, &st)) ret = EEXIST; @@ -2069,14 +2096,22 @@ int finalize_object_file_flags(const char *tmpfile, const char *filename, errno = saved_errno; return error_errno(_("unable to write file %s"), filename); } - if (!(flags & FOF_SKIP_COLLISION_CHECK) && - check_collision(tmpfile, filename)) + if (!(flags & FOF_SKIP_COLLISION_CHECK)) { + ret = check_collision(tmpfile, filename); + if (ret == CHECK_COLLISION_DEST_VANISHED) { + if (retries++ > 5) + return error(_("unable to write repeatedly vanishing file %s"), + filename); + goto retry; + } + else if (ret) return -1; + } unlink_or_warn(tmpfile); } out: - if (adjust_shared_perm(filename)) + if (adjust_shared_perm(the_repository, filename)) return error(_("unable to set permission to '%s'"), filename); return 0; } @@ -2152,7 +2187,7 @@ static int create_tmpfile(struct strbuf *tmp, const char *filename) strbuf_add(tmp, filename, dirlen - 1); if (mkdir(tmp->buf, 0777) && errno != EEXIST) return -1; - if (adjust_shared_perm(tmp->buf)) + if (adjust_shared_perm(the_repository, tmp->buf)) return -1; /* Try again */ @@ -2177,7 +2212,7 @@ static int start_loose_object_common(struct strbuf *tmp_file, const char *filename, unsigned flags, git_zstream *stream, unsigned char *buf, size_t buflen, - git_hash_ctx *c, git_hash_ctx *compat_c, + struct git_hash_ctx *c, struct git_hash_ctx *compat_c, char *hdr, int hdrlen) { struct repository *repo = the_repository; @@ -2211,9 +2246,9 @@ static int start_loose_object_common(struct strbuf *tmp_file, stream->avail_in = hdrlen; while (git_deflate(stream, 0) == Z_OK) ; /* nothing */ - algo->update_fn(c, hdr, hdrlen); + git_hash_update(c, hdr, hdrlen); if (compat && compat_c) - compat->update_fn(compat_c, hdr, hdrlen); + git_hash_update(compat_c, hdr, hdrlen); return fd; } @@ -2222,21 +2257,20 @@ static int start_loose_object_common(struct strbuf *tmp_file, * Common steps for the inner git_deflate() loop for writing loose * objects. Returns what git_deflate() returns. */ -static int write_loose_object_common(git_hash_ctx *c, git_hash_ctx *compat_c, +static int write_loose_object_common(struct git_hash_ctx *c, struct git_hash_ctx *compat_c, git_zstream *stream, const int flush, unsigned char *in0, const int fd, unsigned char *compressed, const size_t compressed_len) { struct repository *repo = the_repository; - const struct git_hash_algo *algo = repo->hash_algo; const struct git_hash_algo *compat = repo->compat_hash_algo; int ret; ret = git_deflate(stream, flush ? Z_FINISH : 0); - algo->update_fn(c, in0, stream->next_in - in0); + git_hash_update(c, in0, stream->next_in - in0); if (compat && compat_c) - compat->update_fn(compat_c, in0, stream->next_in - in0); + git_hash_update(compat_c, in0, stream->next_in - in0); if (write_in_full(fd, compressed, stream->next_out - compressed) < 0) die_errno(_("unable to write loose object file")); stream->next_out = compressed; @@ -2251,21 +2285,20 @@ static int write_loose_object_common(git_hash_ctx *c, git_hash_ctx *compat_c, * - End the compression of zlib stream. * - Get the calculated oid to "oid". */ -static int end_loose_object_common(git_hash_ctx *c, git_hash_ctx *compat_c, +static int end_loose_object_common(struct git_hash_ctx *c, struct git_hash_ctx *compat_c, git_zstream *stream, struct object_id *oid, struct object_id *compat_oid) { struct repository *repo = the_repository; - const struct git_hash_algo *algo = repo->hash_algo; const struct git_hash_algo *compat = repo->compat_hash_algo; int ret; ret = git_deflate_end_gently(stream); if (ret != Z_OK) return ret; - algo->final_oid_fn(oid, c); + git_hash_final_oid(oid, c); if (compat && compat_c) - compat->final_oid_fn(compat_oid, compat_c); + git_hash_final_oid(compat_oid, compat_c); return Z_OK; } @@ -2277,7 +2310,7 @@ static int write_loose_object(const struct object_id *oid, char *hdr, int fd, ret; unsigned char compressed[4096]; git_zstream stream; - git_hash_ctx c; + struct git_hash_ctx c; struct object_id parano_oid; static struct strbuf tmp_file = STRBUF_INIT; static struct strbuf filename = STRBUF_INIT; @@ -2357,7 +2390,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len, int fd, ret, err = 0, flush = 0; unsigned char compressed[4096]; git_zstream stream; - git_hash_ctx c, compat_c; + struct git_hash_ctx c, compat_c; struct strbuf tmp_file = STRBUF_INIT; struct strbuf filename = STRBUF_INIT; int dirlen; @@ -3017,14 +3050,14 @@ static int check_stream_oid(git_zstream *stream, const char *path, const struct object_id *expected_oid) { - git_hash_ctx c; + struct git_hash_ctx c; struct object_id real_oid; unsigned char buf[4096]; unsigned long total_read; int status = Z_OK; the_hash_algo->init_fn(&c); - the_hash_algo->update_fn(&c, hdr, stream->total_out); + git_hash_update(&c, hdr, stream->total_out); /* * We already read some bytes into hdr, but the ones up to the NUL @@ -3044,7 +3077,7 @@ static int check_stream_oid(git_zstream *stream, if (size - total_read < stream->avail_out) stream->avail_out = size - total_read; status = git_inflate(stream, Z_FINISH); - the_hash_algo->update_fn(&c, buf, stream->next_out - buf); + git_hash_update(&c, buf, stream->next_out - buf); total_read += stream->next_out - buf; } git_inflate_end(stream); @@ -3059,7 +3092,7 @@ static int check_stream_oid(git_zstream *stream, return -1; } - the_hash_algo->final_oid_fn(&real_oid, &c); + git_hash_final_oid(&real_oid, &c); if (!oideq(expected_oid, &real_oid)) { error(_("hash mismatch for %s (expected %s)"), path, oid_to_hex(expected_oid)); diff --git a/object-name.c b/object-name.c index 88d1313028..91f731373a 100644 --- a/object-name.c +++ b/object-name.c @@ -961,7 +961,9 @@ static int get_oid_basic(struct repository *r, const char *str, int len, int fatal = !(flags & GET_OID_QUIETLY); if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) { - if (repo_settings_get_warn_ambiguous_refs(r) && warn_on_object_refname_ambiguity) { + if (!(flags & GET_OID_SKIP_AMBIGUITY_CHECK) && + repo_settings_get_warn_ambiguous_refs(r) && + warn_on_object_refname_ambiguity) { refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0); if (refs_found > 0) { warning(warn_msg, len, str); @@ -1272,6 +1274,58 @@ static int peel_onion(struct repository *r, const char *name, int len, return 0; } +/* + * Documentation/revisions.adoc says: + * '<describeOutput>', e.g. 'v1.7.4.2-679-g3bee7fb':: + * Output from `git describe`; i.e. a closest tag, optionally + * followed by a dash and a number of commits, followed by a dash, a + * 'g', and an abbreviated object name. + * + * which means that the stuff before '-g${HASH}' needs to be a valid + * refname, a dash, and a non-negative integer. This function verifies + * that. + * + * In particular, we do not want to treat + * branchname:path/to/file/named/i-gaffed + * as a request for commit affed. + * + * More generally, we should probably not treat + * 'refs/heads/./../.../ ~^:/?*[////\\\&}/busted.lock-g050e0ef6ead' + * as a request for object 050e0ef6ead either. + * + * We are called with name[len] == '-' and name[len+1] == 'g', i.e. + * we are verifying ${REFNAME}-{INTEGER} part of the name. + */ +static int ref_and_count_parts_valid(const char *name, int len) +{ + struct strbuf sb; + const char *cp; + int flags = REFNAME_ALLOW_ONELEVEL; + int ret = 1; + + /* Ensure we have at least one digit */ + if (!isxdigit(name[len-1])) + return 0; + + /* Skip over digits backwards until we get to the dash */ + for (cp = name + len - 2; name < cp; cp--) { + if (*cp == '-') + break; + if (!isxdigit(*cp)) + return 0; + } + /* Ensure we found the leading dash */ + if (*cp != '-') + return 0; + + len = cp - name; + strbuf_init(&sb, len); + strbuf_add(&sb, name, len); + ret = !check_refname_format(sb.buf, flags); + strbuf_release(&sb); + return ret; +} + static int get_describe_name(struct repository *r, const char *name, int len, struct object_id *oid) @@ -1285,7 +1339,8 @@ static int get_describe_name(struct repository *r, /* We must be looking at g in "SOMETHING-g" * for it to be describe output. */ - if (ch == 'g' && cp[-1] == '-') { + if (ch == 'g' && cp[-1] == '-' && + ref_and_count_parts_valid(name, cp - 1 - name)) { cp++; len -= cp - name; return get_short_oid(r, @@ -1741,18 +1796,20 @@ void object_context_release(struct object_context *ctx) strbuf_release(&ctx->symlink_path); } -/* - * This is like "get_oid_basic()", except it allows "object ID expressions", - * notably "xyz^" for "parent of xyz" - */ -int repo_get_oid(struct repository *r, const char *name, struct object_id *oid) +int repo_get_oid_with_flags(struct repository *r, const char *name, + struct object_id *oid, unsigned flags) { struct object_context unused; - int ret = get_oid_with_context(r, name, 0, oid, &unused); + int ret = get_oid_with_context(r, name, flags, oid, &unused); object_context_release(&unused); return ret; } +int repo_get_oid(struct repository *r, const char *name, struct object_id *oid) +{ + return repo_get_oid_with_flags(r, name, oid, 0); +} + /* * This returns a non-zero value if the string (built using printf * format and the given arguments) is not a valid object. @@ -2052,12 +2109,14 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo, return -1; } for (cp = name, bracket_depth = 0; *cp; cp++) { - if (*cp == '{') + if (strchr("@^", *cp) && cp[1] == '{') { + cp++; bracket_depth++; - else if (bracket_depth && *cp == '}') + } else if (bracket_depth && *cp == '}') { bracket_depth--; - else if (!bracket_depth && *cp == ':') + } else if (!bracket_depth && *cp == ':') { break; + } } if (*cp == ':') { struct object_id tree_oid; diff --git a/object-name.h b/object-name.h index 8dba4a47a4..cda4934cd5 100644 --- a/object-name.h +++ b/object-name.h @@ -51,6 +51,12 @@ void strbuf_repo_add_unique_abbrev(struct strbuf *sb, struct repository *repo, void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid, int abbrev_len); +/* + * This is like "get_oid_basic()", except it allows "object ID expressions", + * notably "xyz^" for "parent of xyz". Accepts GET_OID_* flags. + */ +int repo_get_oid_with_flags(struct repository *r, const char *str, + struct object_id *oid, unsigned flags); int repo_get_oid(struct repository *r, const char *str, struct object_id *oid); __attribute__((format (printf, 2, 3))) int get_oidf(struct object_id *oid, const char *fmt, ...); diff --git a/oss-fuzz/fuzz-parse-attr-line.c b/oss-fuzz/fuzz-parse-attr-line.c index e0e4bc6358..315198505c 100644 --- a/oss-fuzz/fuzz-parse-attr-line.c +++ b/oss-fuzz/fuzz-parse-attr-line.c @@ -24,7 +24,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) res = parse_attr_line(buf, "dummy", 0, 0); if (res) { - int j; + size_t j; for (j = 0; j < res->num_attr; j++) { const char *setto = res->state[j].setto; if (ATTR_TRUE(setto) || ATTR_FALSE(setto) || diff --git a/oss-fuzz/meson.build b/oss-fuzz/meson.build new file mode 100644 index 0000000000..878afd8426 --- /dev/null +++ b/oss-fuzz/meson.build @@ -0,0 +1,20 @@ +fuzz_programs = [ + 'fuzz-commit-graph.c', + 'fuzz-config.c', + 'fuzz-credential-from-url-gently.c', + 'fuzz-date.c', + 'fuzz-pack-headers.c', + 'fuzz-pack-idx.c', + 'fuzz-parse-attr-line.c', + 'fuzz-url-decode-mem.c', +] + +foreach fuzz_program : fuzz_programs + executable(fs.stem(fuzz_program), + sources: [ + 'dummy-cmd-main.c', + fuzz_program, + ], + dependencies: [libgit_commonmain], + ) +endforeach diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index 4f8be53c2b..34e86d4994 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -590,7 +590,8 @@ int bitmap_writer_build(struct bitmap_writer *writer) int closed = 1; /* until proven otherwise */ if (writer->show_progress) - writer->progress = start_progress("Building bitmaps", + writer->progress = start_progress(the_repository, + "Building bitmaps", writer->selected_nr); trace2_region_enter("pack-bitmap-write", "building_bitmaps_total", the_repository); @@ -710,7 +711,8 @@ void bitmap_writer_select_commits(struct bitmap_writer *writer, } if (writer->show_progress) - writer->progress = start_progress("Selecting bitmap commits", 0); + writer->progress = start_progress(the_repository, + "Selecting bitmap commits", 0); for (;;) { struct commit *chosen = NULL; @@ -1070,7 +1072,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer, finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE); - if (adjust_shared_perm(tmp_file.buf)) + if (adjust_shared_perm(the_repository, tmp_file.buf)) die_errno("unable to make temporary bitmap file readable"); if (rename(tmp_file.buf, filename)) diff --git a/pack-bitmap.c b/pack-bitmap.c index 60b5da9d0b..6406953d32 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -2573,7 +2573,9 @@ void test_bitmap_walk(struct rev_info *revs) tdata.trees = ewah_to_bitmap(bitmap_git->trees); tdata.blobs = ewah_to_bitmap(bitmap_git->blobs); tdata.tags = ewah_to_bitmap(bitmap_git->tags); - tdata.prg = start_progress("Verifying bitmap entries", result_popcnt); + tdata.prg = start_progress(revs->repo, + "Verifying bitmap entries", + result_popcnt); tdata.seen = 0; traverse_commit_list(revs, &test_show_commit, &test_show_object, &tdata); diff --git a/pack-check.c b/pack-check.c index 8d9f6da7ce..d0aeb5ec41 100644 --- a/pack-check.c +++ b/pack-check.c @@ -58,7 +58,7 @@ static int verify_packfile(struct repository *r, { off_t index_size = p->index_size; const unsigned char *index_base = p->index_data; - git_hash_ctx ctx; + struct git_hash_ctx ctx; unsigned char hash[GIT_MAX_RAWSZ], *pack_sig; off_t offset = 0, pack_sig_ofs = 0; uint32_t nr_objects, i; @@ -77,9 +77,9 @@ static int verify_packfile(struct repository *r, pack_sig_ofs = p->pack_size - r->hash_algo->rawsz; if (offset > pack_sig_ofs) remaining -= (unsigned int)(offset - pack_sig_ofs); - r->hash_algo->update_fn(&ctx, in, remaining); + git_hash_update(&ctx, in, remaining); } while (offset < pack_sig_ofs); - r->hash_algo->final_fn(hash, &ctx); + git_hash_final(hash, &ctx); pack_sig = use_pack(p, w_curs, pack_sig_ofs, NULL); if (!hasheq(hash, pack_sig, the_repository->hash_algo)) err = error("%s pack checksum mismatch", diff --git a/pack-objects.h b/pack-objects.h index 3f6f504203..d73e3843c9 100644 --- a/pack-objects.h +++ b/pack-objects.h @@ -208,6 +208,34 @@ static inline uint32_t pack_name_hash(const char *name) return hash; } +static inline uint32_t pack_name_hash_v2(const unsigned char *name) +{ + uint32_t hash = 0, base = 0, c; + + if (!name) + return 0; + + while ((c = *name++)) { + if (isspace(c)) + continue; + if (c == '/') { + base = (base >> 6) ^ hash; + hash = 0; + } else { + /* + * 'c' is only a single byte. Reverse it and move + * it to the top of the hash, moving the rest to + * less-significant bits. + */ + c = (c & 0xF0) >> 4 | (c & 0x0F) << 4; + c = (c & 0xCC) >> 2 | (c & 0x33) << 2; + c = (c & 0xAA) >> 1 | (c & 0x55) << 1; + hash = (hash >> 2) + (c << 24); + } + } + return (base >> 6) ^ hash; +} + static inline enum object_type oe_type(const struct object_entry *e) { return e->type_valid ? e->type_ : OBJ_BAD; diff --git a/pack-write.c b/pack-write.c index 98a8c0e785..823e40b42f 100644 --- a/pack-write.c +++ b/pack-write.c @@ -56,7 +56,8 @@ static int need_large_offset(off_t offset, const struct pack_idx_option *opts) * The *sha1 contains the pack content SHA1 hash. * The objects array passed in will be sorted by SHA1 on exit. */ -const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, +const char *write_idx_file(const struct git_hash_algo *hash_algo, + const char *index_name, struct pack_idx_entry **objects, int nr_objects, const struct pack_idx_option *opts, const unsigned char *sha1) { @@ -130,7 +131,7 @@ const char *write_idx_file(const char *index_name, struct pack_idx_entry **objec struct pack_idx_entry *obj = *list++; if (index_version < 2) hashwrite_be32(f, obj->offset); - hashwrite(f, obj->oid.hash, the_hash_algo->rawsz); + hashwrite(f, obj->oid.hash, hash_algo->rawsz); if ((opts->flags & WRITE_IDX_STRICT) && (i && oideq(&list[-2]->oid, &obj->oid))) die("The same object %s appears twice in the pack", @@ -172,7 +173,7 @@ const char *write_idx_file(const char *index_name, struct pack_idx_entry **objec } } - hashwrite(f, sha1, the_hash_algo->rawsz); + hashwrite(f, sha1, hash_algo->rawsz); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, CSUM_HASH_IN_STREAM | CSUM_CLOSE | ((opts->flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC)); @@ -193,11 +194,12 @@ static int pack_order_cmp(const void *va, const void *vb, void *ctx) return 0; } -static void write_rev_header(struct hashfile *f) +static void write_rev_header(const struct git_hash_algo *hash_algo, + struct hashfile *f) { hashwrite_be32(f, RIDX_SIGNATURE); hashwrite_be32(f, RIDX_VERSION); - hashwrite_be32(f, oid_version(the_hash_algo)); + hashwrite_be32(f, oid_version(hash_algo)); } static void write_rev_index_positions(struct hashfile *f, @@ -209,12 +211,14 @@ static void write_rev_index_positions(struct hashfile *f, hashwrite_be32(f, pack_order[i]); } -static void write_rev_trailer(struct hashfile *f, const unsigned char *hash) +static void write_rev_trailer(const struct git_hash_algo *hash_algo, + struct hashfile *f, const unsigned char *hash) { - hashwrite(f, hash, the_hash_algo->rawsz); + hashwrite(f, hash, hash_algo->rawsz); } -char *write_rev_file(const char *rev_name, +char *write_rev_file(const struct git_hash_algo *hash_algo, + const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, @@ -232,15 +236,16 @@ char *write_rev_file(const char *rev_name, pack_order[i] = i; QSORT_S(pack_order, nr_objects, pack_order_cmp, objects); - ret = write_rev_file_order(rev_name, pack_order, nr_objects, hash, - flags); + ret = write_rev_file_order(hash_algo, rev_name, pack_order, nr_objects, + hash, flags); free(pack_order); return ret; } -char *write_rev_file_order(const char *rev_name, +char *write_rev_file_order(const struct git_hash_algo *hash_algo, + const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, const unsigned char *hash, @@ -279,12 +284,12 @@ char *write_rev_file_order(const char *rev_name, return NULL; } - write_rev_header(f); + write_rev_header(hash_algo, f); write_rev_index_positions(f, pack_order, nr_objects); - write_rev_trailer(f, hash); + write_rev_trailer(hash_algo, f, hash); - if (adjust_shared_perm(path) < 0) + if (adjust_shared_perm(the_repository, path) < 0) die(_("failed to make %s readable"), path); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, @@ -294,11 +299,12 @@ char *write_rev_file_order(const char *rev_name, return path; } -static void write_mtimes_header(struct hashfile *f) +static void write_mtimes_header(const struct git_hash_algo *hash_algo, + struct hashfile *f) { hashwrite_be32(f, MTIMES_SIGNATURE); hashwrite_be32(f, MTIMES_VERSION); - hashwrite_be32(f, oid_version(the_hash_algo)); + hashwrite_be32(f, oid_version(hash_algo)); } /* @@ -318,12 +324,14 @@ static void write_mtimes_objects(struct hashfile *f, } } -static void write_mtimes_trailer(struct hashfile *f, const unsigned char *hash) +static void write_mtimes_trailer(const struct git_hash_algo *hash_algo, + struct hashfile *f, const unsigned char *hash) { - hashwrite(f, hash, the_hash_algo->rawsz); + hashwrite(f, hash, hash_algo->rawsz); } -static char *write_mtimes_file(struct packing_data *to_pack, +static char *write_mtimes_file(const struct git_hash_algo *hash_algo, + struct packing_data *to_pack, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash) @@ -340,11 +348,11 @@ static char *write_mtimes_file(struct packing_data *to_pack, mtimes_name = strbuf_detach(&tmp_file, NULL); f = hashfd(fd, mtimes_name); - write_mtimes_header(f); + write_mtimes_header(hash_algo, f); write_mtimes_objects(f, to_pack, objects, nr_objects); - write_mtimes_trailer(f, hash); + write_mtimes_trailer(hash_algo, f, hash); - if (adjust_shared_perm(mtimes_name) < 0) + if (adjust_shared_perm(the_repository, mtimes_name) < 0) die(_("failed to make %s readable"), mtimes_name); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, @@ -380,7 +388,8 @@ off_t write_pack_header(struct hashfile *f, uint32_t nr_entries) * partial_pack_sha1 can refer to the same buffer if the caller is not * interested in the resulting SHA1 of pack data above partial_pack_offset. */ -void fixup_pack_header_footer(int pack_fd, +void fixup_pack_header_footer(const struct git_hash_algo *hash_algo, + int pack_fd, unsigned char *new_pack_hash, const char *pack_name, uint32_t object_count, @@ -388,13 +397,13 @@ void fixup_pack_header_footer(int pack_fd, off_t partial_pack_offset) { int aligned_sz, buf_sz = 8 * 1024; - git_hash_ctx old_hash_ctx, new_hash_ctx; + struct git_hash_ctx old_hash_ctx, new_hash_ctx; struct pack_header hdr; char *buf; ssize_t read_result; - the_hash_algo->init_fn(&old_hash_ctx); - the_hash_algo->init_fn(&new_hash_ctx); + hash_algo->init_fn(&old_hash_ctx); + hash_algo->init_fn(&new_hash_ctx); if (lseek(pack_fd, 0, SEEK_SET) != 0) die_errno("Failed seeking to start of '%s'", pack_name); @@ -406,9 +415,9 @@ void fixup_pack_header_footer(int pack_fd, pack_name); if (lseek(pack_fd, 0, SEEK_SET) != 0) die_errno("Failed seeking to start of '%s'", pack_name); - the_hash_algo->update_fn(&old_hash_ctx, &hdr, sizeof(hdr)); + git_hash_update(&old_hash_ctx, &hdr, sizeof(hdr)); hdr.hdr_entries = htonl(object_count); - the_hash_algo->update_fn(&new_hash_ctx, &hdr, sizeof(hdr)); + git_hash_update(&new_hash_ctx, &hdr, sizeof(hdr)); write_or_die(pack_fd, &hdr, sizeof(hdr)); partial_pack_offset -= sizeof(hdr); @@ -423,7 +432,7 @@ void fixup_pack_header_footer(int pack_fd, break; if (n < 0) die_errno("Failed to checksum '%s'", pack_name); - the_hash_algo->update_fn(&new_hash_ctx, buf, n); + git_hash_update(&new_hash_ctx, buf, n); aligned_sz -= n; if (!aligned_sz) @@ -432,13 +441,13 @@ void fixup_pack_header_footer(int pack_fd, if (!partial_pack_hash) continue; - the_hash_algo->update_fn(&old_hash_ctx, buf, n); + git_hash_update(&old_hash_ctx, buf, n); partial_pack_offset -= n; if (partial_pack_offset == 0) { unsigned char hash[GIT_MAX_RAWSZ]; - the_hash_algo->final_fn(hash, &old_hash_ctx); + git_hash_final(hash, &old_hash_ctx); if (!hasheq(hash, partial_pack_hash, - the_repository->hash_algo)) + hash_algo)) die("Unexpected checksum for %s " "(disk corruption?)", pack_name); /* @@ -446,7 +455,7 @@ void fixup_pack_header_footer(int pack_fd, * pack, which also means making partial_pack_offset * big enough not to matter anymore. */ - the_hash_algo->init_fn(&old_hash_ctx); + hash_algo->init_fn(&old_hash_ctx); partial_pack_offset = ~partial_pack_offset; partial_pack_offset -= MSB(partial_pack_offset, 1); } @@ -454,16 +463,16 @@ void fixup_pack_header_footer(int pack_fd, free(buf); if (partial_pack_hash) - the_hash_algo->final_fn(partial_pack_hash, &old_hash_ctx); - the_hash_algo->final_fn(new_pack_hash, &new_hash_ctx); - write_or_die(pack_fd, new_pack_hash, the_hash_algo->rawsz); + git_hash_final(partial_pack_hash, &old_hash_ctx); + git_hash_final(new_pack_hash, &new_hash_ctx); + write_or_die(pack_fd, new_pack_hash, hash_algo->rawsz); fsync_component_or_die(FSYNC_COMPONENT_PACK, pack_fd, pack_name); } -char *index_pack_lockfile(int ip_out, int *is_well_formed) +char *index_pack_lockfile(struct repository *r, int ip_out, int *is_well_formed) { char packname[GIT_MAX_HEXSZ + 6]; - const int len = the_hash_algo->hexsz + 6; + const int len = r->hash_algo->hexsz + 6; /* * The first thing we expect from index-pack's output @@ -480,7 +489,7 @@ char *index_pack_lockfile(int ip_out, int *is_well_formed) packname[len-1] = 0; if (skip_prefix(packname, "keep\t", &name)) return xstrfmt("%s/pack/pack-%s.keep", - repo_get_object_directory(the_repository), name); + repo_get_object_directory(r), name); return NULL; } if (is_well_formed) @@ -546,7 +555,8 @@ void rename_tmp_packfile_idx(struct strbuf *name_buffer, rename_tmp_packfile(name_buffer, *idx_tmp_name, "idx"); } -void stage_tmp_packfiles(struct strbuf *name_buffer, +void stage_tmp_packfiles(const struct git_hash_algo *hash_algo, + struct strbuf *name_buffer, const char *pack_tmp_name, struct pack_idx_entry **written_list, uint32_t nr_written, @@ -558,20 +568,20 @@ void stage_tmp_packfiles(struct strbuf *name_buffer, char *rev_tmp_name = NULL; char *mtimes_tmp_name = NULL; - if (adjust_shared_perm(pack_tmp_name)) + if (adjust_shared_perm(the_repository, pack_tmp_name)) die_errno("unable to make temporary pack file readable"); - *idx_tmp_name = (char *)write_idx_file(NULL, written_list, nr_written, - pack_idx_opts, hash); - if (adjust_shared_perm(*idx_tmp_name)) + *idx_tmp_name = (char *)write_idx_file(hash_algo, NULL, written_list, + nr_written, pack_idx_opts, hash); + if (adjust_shared_perm(the_repository, *idx_tmp_name)) die_errno("unable to make temporary index file readable"); - rev_tmp_name = write_rev_file(NULL, written_list, nr_written, hash, - pack_idx_opts->flags); + rev_tmp_name = write_rev_file(hash_algo, NULL, written_list, nr_written, + hash, pack_idx_opts->flags); if (pack_idx_opts->flags & WRITE_MTIMES) { - mtimes_tmp_name = write_mtimes_file(to_pack, written_list, - nr_written, + mtimes_tmp_name = write_mtimes_file(hash_algo, to_pack, + written_list, nr_written, hash); } @@ -13,7 +13,8 @@ struct repository; */ #define PACK_SIGNATURE 0x5041434b /* "PACK" */ #define PACK_VERSION 2 -#define pack_version_ok(v) ((v) == htonl(2) || (v) == htonl(3)) +#define pack_version_ok(v) pack_version_ok_native(ntohl(v)) +#define pack_version_ok_native(v) ((v) == 2 || (v) == 3) struct pack_header { uint32_t hdr_signature; uint32_t hdr_version; @@ -86,20 +87,37 @@ struct progress; /* Note, the data argument could be NULL if object type is blob */ typedef int (*verify_fn)(const struct object_id *, enum object_type, unsigned long, void*, int*); -const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, const struct pack_idx_option *, const unsigned char *sha1); +const char *write_idx_file(const struct git_hash_algo *hash_algo, + const char *index_name, + struct pack_idx_entry **objects, + int nr_objects, + const struct pack_idx_option *, + const unsigned char *sha1); int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr); int verify_pack_index(struct packed_git *); int verify_pack(struct repository *, struct packed_git *, verify_fn fn, struct progress *, uint32_t); off_t write_pack_header(struct hashfile *f, uint32_t); -void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t, unsigned char *, off_t); -char *index_pack_lockfile(int fd, int *is_well_formed); +void fixup_pack_header_footer(const struct git_hash_algo *, int, + unsigned char *, const char *, uint32_t, + unsigned char *, off_t); +char *index_pack_lockfile(struct repository *r, int fd, int *is_well_formed); struct ref; void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought); -char *write_rev_file(const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, unsigned flags); -char *write_rev_file_order(const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, const unsigned char *hash, unsigned flags); +char *write_rev_file(const struct git_hash_algo *hash_algo, + const char *rev_name, + struct pack_idx_entry **objects, + uint32_t nr_objects, + const unsigned char *hash, + unsigned flags); +char *write_rev_file_order(const struct git_hash_algo *hash_algo, + const char *rev_name, + uint32_t *pack_order, + uint32_t nr_objects, + const unsigned char *hash, + unsigned flags); /* * The "hdr" output buffer should be at least this big, which will handle sizes @@ -117,7 +135,8 @@ int read_pack_header(int fd, struct pack_header *); struct packing_data; struct hashfile *create_tmp_packfile(char **pack_tmp_name); -void stage_tmp_packfiles(struct strbuf *name_buffer, +void stage_tmp_packfiles(const struct git_hash_algo *hash_algo, + struct strbuf *name_buffer, const char *pack_tmp_name, struct pack_idx_entry **written_list, uint32_t nr_written, diff --git a/packfile.c b/packfile.c index cc7ab6403a..9d09f8bc72 100644 --- a/packfile.c +++ b/packfile.c @@ -24,6 +24,7 @@ #include "commit-graph.h" #include "pack-revindex.h" #include "promisor-remote.h" +#include "pack-mtimes.h" char *odb_pack_name(struct repository *r, struct strbuf *buf, const unsigned char *hash, const char *ext) @@ -2107,7 +2108,7 @@ static void maybe_invalidate_kept_pack_cache(struct repository *r, r->objects->kept_pack_cache.flags = 0; } -static struct packed_git **kept_pack_cache(struct repository *r, unsigned flags) +struct packed_git **kept_pack_cache(struct repository *r, unsigned flags) { maybe_invalidate_kept_pack_cache(r, flags); @@ -2315,3 +2316,23 @@ int is_promisor_object(struct repository *r, const struct object_id *oid) } return oidset_contains(&promisor_objects, oid); } + +int parse_pack_header_option(const char *in, unsigned char *out, unsigned int *len) +{ + unsigned char *hdr; + char *c; + + hdr = out; + put_be32(hdr, PACK_SIGNATURE); + hdr += 4; + put_be32(hdr, strtoul(in, &c, 10)); + hdr += 4; + if (*c != ',') + return -1; + put_be32(hdr, strtoul(c + 1, &c, 10)); + hdr += 4; + if (*c) + return -1; + *len = hdr - out; + return 0; +} diff --git a/packfile.h b/packfile.h index 58104fa009..25097213d0 100644 --- a/packfile.h +++ b/packfile.h @@ -197,6 +197,8 @@ int has_object_pack(struct repository *r, const struct object_id *oid); int has_object_kept_pack(struct repository *r, const struct object_id *oid, unsigned flags); +struct packed_git **kept_pack_cache(struct repository *r, unsigned flags); + /* * Return 1 if an object in a promisor packfile is or refers to the given * object, 0 otherwise. @@ -216,4 +218,10 @@ int is_promisor_object(struct repository *r, const struct object_id *oid); int load_idx(const char *path, const unsigned int hashsz, void *idx_map, size_t idx_size, struct packed_git *p); +/* + * Parse a --pack_header option as accepted by index-pack and unpack-objects, + * turning it into the matching bytes we'd find in a pack. + */ +int parse_pack_header_option(const char *in, unsigned char *out, unsigned int *len); + #endif @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "config.h" #include "editor.h" @@ -84,7 +82,7 @@ static int core_pager_config(const char *var, const char *value, return 0; } -const char *git_pager(int stdout_is_tty) +const char *git_pager(struct repository *r, int stdout_is_tty) { const char *pager; @@ -94,7 +92,7 @@ const char *git_pager(int stdout_is_tty) pager = getenv("GIT_PAGER"); if (!pager) { if (!pager_program) - read_early_config(the_repository, + read_early_config(r, core_pager_config, NULL); pager = pager_program; } @@ -143,10 +141,10 @@ void prepare_pager_args(struct child_process *pager_process, const char *pager) pager_process->trace2_child_class = "pager"; } -void setup_pager(void) +void setup_pager(struct repository *r) { static int once = 0; - const char *pager = git_pager(isatty(1)); + const char *pager = git_pager(r, isatty(1)); if (!pager) return; @@ -293,7 +291,7 @@ static int pager_command_config(const char *var, const char *value, } /* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */ -int check_pager_config(const char *cmd) +int check_pager_config(struct repository *r, const char *cmd) { struct pager_command_config_data data; @@ -301,7 +299,7 @@ int check_pager_config(const char *cmd) data.want = -1; data.value = NULL; - read_early_config(the_repository, pager_command_config, &data); + read_early_config(r, pager_command_config, &data); if (data.value) pager_program = data.value; @@ -2,15 +2,16 @@ #define PAGER_H struct child_process; +struct repository; -const char *git_pager(int stdout_is_tty); -void setup_pager(void); +const char *git_pager(struct repository *r, int stdout_is_tty); +void setup_pager(struct repository *r); void wait_for_pager(void); int pager_in_use(void); int term_columns(void); void term_clear_line(void); int decimal_width(uintmax_t); -int check_pager_config(const char *cmd); +int check_pager_config(struct repository *r, const char *cmd); void prepare_pager_args(struct child_process *, const char *pager); extern int pager_use_color; diff --git a/parse-options.c b/parse-options.c index 33bfba0ed4..35fbb3b0d6 100644 --- a/parse-options.c +++ b/parse-options.c @@ -1076,11 +1076,48 @@ static int usage_argh(const struct option *opts, FILE *outfile) !opts->argh || !!strpbrk(opts->argh, "()<>[]|"); if (opts->flags & PARSE_OPT_OPTARG) if (opts->long_name) - s = literal ? "[=%s]" : "[=<%s>]"; + /* + * TRANSLATORS: The "<%s>" part of this string + * stands for an optional value given to a command + * line option in the long form, and "<>" is there + * as a convention to signal that it is a + * placeholder (i.e. the user should substitute it + * with the real value). If your language uses a + * different convention, you can change "<%s>" part + * to match yours, e.g. it might use "|%s|" instead, + * or if the alphabet is different enough it may use + * "%s" without any placeholder signal. Most + * translations leave this message as is. + */ + s = literal ? "[=%s]" : _("[=<%s>]"); else - s = literal ? "[%s]" : "[<%s>]"; + /* + * TRANSLATORS: The "<%s>" part of this string + * stands for an optional value given to a command + * line option in the short form, and "<>" is there + * as a convention to signal that it is a + * placeholder (i.e. the user should substitute it + * with the real value). If your language uses a + * different convention, you can change "<%s>" part + * to match yours, e.g. it might use "|%s|" instead, + * or if the alphabet is different enough it may use + * "%s" without any placeholder signal. Most + * translations leave this message as is. + */ + s = literal ? "[%s]" : _("[<%s>]"); else - s = literal ? " %s" : " <%s>"; + /* + * TRANSLATORS: The "<%s>" part of this string stands for a + * value given to a command line option, and "<>" is there + * as a convention to signal that it is a placeholder + * (i.e. the user should substitute it with the real value). + * If your language uses a different convention, you can + * change "<%s>" part to match yours, e.g. it might use + * "|%s|" instead, or if the alphabet is different enough it + * may use "%s" without any placeholder signal. Most + * translations leave this message as is. + */ + s = literal ? " %s" : _(" <%s>"); return utf8_fprintf(outfile, s, opts->argh ? _(opts->argh) : _("...")); } @@ -1282,6 +1319,16 @@ void NORETURN usage_with_options(const char * const *usagestr, exit(129); } +void show_usage_with_options_if_asked(int ac, const char **av, + const char * const *usagestr, + const struct option *opts) +{ + if (ac == 2 && !strcmp(av[1], "-h")) { + usage_with_options_internal(NULL, usagestr, opts, 0, 0); + exit(129); + } +} + void NORETURN usage_msg_opt(const char *msg, const char * const *usagestr, const struct option *options) diff --git a/parse-options.h b/parse-options.h index d01361ca97..997ffbee80 100644 --- a/parse-options.h +++ b/parse-options.h @@ -6,7 +6,7 @@ struct repository; /** - * Refer to Documentation/technical/api-parse-options.txt for the API doc. + * Refer to Documentation/technical/api-parse-options.adoc for the API doc. */ enum parse_opt_type { @@ -402,6 +402,10 @@ int parse_options(int argc, const char **argv, const char *prefix, NORETURN void usage_with_options(const char * const *usagestr, const struct option *options); +void show_usage_with_options_if_asked(int ac, const char **av, + const char * const *usage, + const struct option *options); + NORETURN void usage_msg_opt(const char *msg, const char * const *usagestr, const struct option *options); @@ -432,6 +436,15 @@ static inline void die_for_incompatible_opt3(int opt1, const char *opt1_name, 0, ""); } +static inline void die_for_incompatible_opt2(int opt1, const char *opt1_name, + int opt2, const char *opt2_name) +{ + die_for_incompatible_opt4(opt1, opt1_name, + opt2, opt2_name, + 0, "", + 0, ""); +} + /* * Use these assertions for callbacks that expect to be called with NONEG and * NOARG respectively, and do not otherwise handle the "unset" and "arg" diff --git a/path-walk.c b/path-walk.c new file mode 100644 index 0000000000..341bdd2ba4 --- /dev/null +++ b/path-walk.c @@ -0,0 +1,609 @@ +/* + * path-walk.c: implementation for path-based walks of the object graph. + */ +#include "git-compat-util.h" +#include "path-walk.h" +#include "blob.h" +#include "commit.h" +#include "dir.h" +#include "hashmap.h" +#include "hex.h" +#include "list-objects.h" +#include "object.h" +#include "oid-array.h" +#include "prio-queue.h" +#include "repository.h" +#include "revision.h" +#include "string-list.h" +#include "strmap.h" +#include "tag.h" +#include "trace2.h" +#include "tree.h" +#include "tree-walk.h" + +static const char *root_path = ""; + +struct type_and_oid_list { + enum object_type type; + struct oid_array oids; + int maybe_interesting; +}; + +#define TYPE_AND_OID_LIST_INIT { \ + .type = OBJ_NONE, \ + .oids = OID_ARRAY_INIT \ +} + +struct path_walk_context { + /** + * Repeats of data in 'struct path_walk_info' for + * access with fewer characters. + */ + struct repository *repo; + struct rev_info *revs; + struct path_walk_info *info; + + /** + * Map a path to a 'struct type_and_oid_list' + * containing the objects discovered at that + * path. + */ + struct strmap paths_to_lists; + + /** + * Store the current list of paths in a priority queue, + * using object type as a sorting mechanism, mostly to + * make sure blobs are popped off the stack first. No + * other sort is made, so within each object type it acts + * like a stack and performs a DFS within the trees. + * + * Use path_stack_pushed to indicate whether a path + * was previously added to path_stack. + */ + struct prio_queue path_stack; + struct strset path_stack_pushed; +}; + +static int compare_by_type(const void *one, const void *two, void *cb_data) +{ + struct type_and_oid_list *list1, *list2; + const char *str1 = one; + const char *str2 = two; + struct path_walk_context *ctx = cb_data; + + list1 = strmap_get(&ctx->paths_to_lists, str1); + list2 = strmap_get(&ctx->paths_to_lists, str2); + + /* + * If object types are equal, then use path comparison. + */ + if (!list1 || !list2 || list1->type == list2->type) + return strcmp(str1, str2); + + /* Prefer tags to be popped off first. */ + if (list1->type == OBJ_TAG) + return -1; + if (list2->type == OBJ_TAG) + return 1; + + /* Prefer blobs to be popped off second. */ + if (list1->type == OBJ_BLOB) + return -1; + if (list2->type == OBJ_BLOB) + return 1; + + return 0; +} + +static void push_to_stack(struct path_walk_context *ctx, + const char *path) +{ + if (strset_contains(&ctx->path_stack_pushed, path)) + return; + + strset_add(&ctx->path_stack_pushed, path); + prio_queue_put(&ctx->path_stack, xstrdup(path)); +} + +static int add_tree_entries(struct path_walk_context *ctx, + const char *base_path, + struct object_id *oid) +{ + struct tree_desc desc; + struct name_entry entry; + struct strbuf path = STRBUF_INIT; + size_t base_len; + struct tree *tree = lookup_tree(ctx->repo, oid); + + if (!tree) { + error(_("failed to walk children of tree %s: not found"), + oid_to_hex(oid)); + return -1; + } else if (parse_tree_gently(tree, 1)) { + error("bad tree object %s", oid_to_hex(oid)); + return -1; + } + + strbuf_addstr(&path, base_path); + base_len = path.len; + + init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); + while (tree_entry(&desc, &entry)) { + struct type_and_oid_list *list; + struct object *o; + /* Not actually true, but we will ignore submodules later. */ + enum object_type type = S_ISDIR(entry.mode) ? OBJ_TREE : OBJ_BLOB; + + /* Skip submodules. */ + if (S_ISGITLINK(entry.mode)) + continue; + + /* If the caller doesn't want blobs, then don't bother. */ + if (!ctx->info->blobs && type == OBJ_BLOB) + continue; + + if (type == OBJ_TREE) { + struct tree *child = lookup_tree(ctx->repo, &entry.oid); + o = child ? &child->object : NULL; + } else if (type == OBJ_BLOB) { + struct blob *child = lookup_blob(ctx->repo, &entry.oid); + o = child ? &child->object : NULL; + } else { + BUG("invalid type for tree entry: %d", type); + } + + if (!o) { + error(_("failed to find object %s"), + oid_to_hex(&o->oid)); + return -1; + } + + /* Skip this object if already seen. */ + if (o->flags & SEEN) + continue; + o->flags |= SEEN; + + strbuf_setlen(&path, base_len); + strbuf_add(&path, entry.path, entry.pathlen); + + /* + * Trees will end with "/" for concatenation and distinction + * from blobs at the same path. + */ + if (type == OBJ_TREE) + strbuf_addch(&path, '/'); + + if (ctx->info->pl) { + int dtype; + enum pattern_match_result match; + match = path_matches_pattern_list(path.buf, path.len, + path.buf + base_len, &dtype, + ctx->info->pl, + ctx->repo->index); + + if (ctx->info->pl->use_cone_patterns && + match == NOT_MATCHED) + continue; + else if (!ctx->info->pl->use_cone_patterns && + type == OBJ_BLOB && + match != MATCHED) + continue; + } + + if (!(list = strmap_get(&ctx->paths_to_lists, path.buf))) { + CALLOC_ARRAY(list, 1); + list->type = type; + strmap_put(&ctx->paths_to_lists, path.buf, list); + } + push_to_stack(ctx, path.buf); + + if (!(o->flags & UNINTERESTING)) + list->maybe_interesting = 1; + + oid_array_append(&list->oids, &entry.oid); + } + + free_tree_buffer(tree); + strbuf_release(&path); + return 0; +} + +/* + * For each path in paths_to_explore, walk the trees another level + * and add any found blobs to the batch (but only if they exist and + * haven't been added yet). + */ +static int walk_path(struct path_walk_context *ctx, + const char *path) +{ + struct type_and_oid_list *list; + int ret = 0; + + list = strmap_get(&ctx->paths_to_lists, path); + + if (!list) + BUG("provided path '%s' that had no associated list", path); + + if (!list->oids.nr) + return 0; + + if (ctx->info->prune_all_uninteresting) { + /* + * This is true if all objects were UNINTERESTING + * when added to the list. + */ + if (!list->maybe_interesting) + return 0; + + /* + * But it's still possible that the objects were set + * as UNINTERESTING after being added. Do a quick check. + */ + list->maybe_interesting = 0; + for (size_t i = 0; + !list->maybe_interesting && i < list->oids.nr; + i++) { + if (list->type == OBJ_TREE) { + struct tree *t = lookup_tree(ctx->repo, + &list->oids.oid[i]); + if (t && !(t->object.flags & UNINTERESTING)) + list->maybe_interesting = 1; + } else if (list->type == OBJ_BLOB) { + struct blob *b = lookup_blob(ctx->repo, + &list->oids.oid[i]); + if (b && !(b->object.flags & UNINTERESTING)) + list->maybe_interesting = 1; + } else { + /* Tags are always interesting if visited. */ + list->maybe_interesting = 1; + } + } + + /* We have confirmed that all objects are UNINTERESTING. */ + if (!list->maybe_interesting) + return 0; + } + + /* Evaluate function pointer on this data, if requested. */ + if ((list->type == OBJ_TREE && ctx->info->trees) || + (list->type == OBJ_BLOB && ctx->info->blobs) || + (list->type == OBJ_TAG && ctx->info->tags)) + ret = ctx->info->path_fn(path, &list->oids, list->type, + ctx->info->path_fn_data); + + /* Expand data for children. */ + if (list->type == OBJ_TREE) { + for (size_t i = 0; i < list->oids.nr; i++) { + ret |= add_tree_entries(ctx, + path, + &list->oids.oid[i]); + } + } + + oid_array_clear(&list->oids); + strmap_remove(&ctx->paths_to_lists, path, 1); + return ret; +} + +static void clear_paths_to_lists(struct strmap *map) +{ + struct hashmap_iter iter; + struct strmap_entry *e; + + hashmap_for_each_entry(&map->map, &iter, e, ent) { + struct type_and_oid_list *list = e->value; + oid_array_clear(&list->oids); + } + strmap_clear(map, 1); + strmap_init(map); +} + +static struct repository *edge_repo; +static struct type_and_oid_list *edge_tree_list; + +static void show_edge(struct commit *commit) +{ + struct tree *t = repo_get_commit_tree(edge_repo, commit); + + if (!t) + return; + + if (commit->object.flags & UNINTERESTING) + t->object.flags |= UNINTERESTING; + + if (t->object.flags & SEEN) + return; + t->object.flags |= SEEN; + + oid_array_append(&edge_tree_list->oids, &t->object.oid); +} + +static int setup_pending_objects(struct path_walk_info *info, + struct path_walk_context *ctx) +{ + struct type_and_oid_list *tags = NULL; + struct type_and_oid_list *tagged_blobs = NULL; + struct type_and_oid_list *root_tree_list = NULL; + + if (info->tags) + CALLOC_ARRAY(tags, 1); + if (info->blobs) + CALLOC_ARRAY(tagged_blobs, 1); + if (info->trees) + root_tree_list = strmap_get(&ctx->paths_to_lists, root_path); + + /* + * Pending objects include: + * * Commits at branch tips. + * * Annotated tags at tag tips. + * * Any kind of object at lightweight tag tips. + * * Trees and blobs in the index (with an associated path). + */ + for (size_t i = 0; i < info->revs->pending.nr; i++) { + struct object_array_entry *pending = info->revs->pending.objects + i; + struct object *obj = pending->item; + + /* Commits will be picked up by revision walk. */ + if (obj->type == OBJ_COMMIT) + continue; + + /* Navigate annotated tag object chains. */ + while (obj->type == OBJ_TAG) { + struct tag *tag = lookup_tag(info->revs->repo, &obj->oid); + if (!tag) { + error(_("failed to find tag %s"), + oid_to_hex(&obj->oid)); + return -1; + } + if (tag->object.flags & SEEN) + break; + tag->object.flags |= SEEN; + + if (tags) + oid_array_append(&tags->oids, &obj->oid); + obj = tag->tagged; + } + + if (obj->type == OBJ_TAG) + continue; + + /* We are now at a non-tag object. */ + if (obj->flags & SEEN) + continue; + obj->flags |= SEEN; + + switch (obj->type) { + case OBJ_TREE: + if (!info->trees) + continue; + if (pending->path) { + struct type_and_oid_list *list; + char *path = *pending->path ? xstrfmt("%s/", pending->path) + : xstrdup(""); + if (!(list = strmap_get(&ctx->paths_to_lists, path))) { + CALLOC_ARRAY(list, 1); + list->type = OBJ_TREE; + strmap_put(&ctx->paths_to_lists, path, list); + } + oid_array_append(&list->oids, &obj->oid); + free(path); + } else { + /* assume a root tree, such as a lightweight tag. */ + oid_array_append(&root_tree_list->oids, &obj->oid); + } + break; + + case OBJ_BLOB: + if (!info->blobs) + continue; + if (pending->path) { + struct type_and_oid_list *list; + char *path = pending->path; + if (!(list = strmap_get(&ctx->paths_to_lists, path))) { + CALLOC_ARRAY(list, 1); + list->type = OBJ_BLOB; + strmap_put(&ctx->paths_to_lists, path, list); + } + oid_array_append(&list->oids, &obj->oid); + } else { + /* assume a root tree, such as a lightweight tag. */ + oid_array_append(&tagged_blobs->oids, &obj->oid); + } + break; + + case OBJ_COMMIT: + /* Make sure it is in the object walk */ + if (obj != pending->item) + add_pending_object(info->revs, obj, ""); + break; + + default: + BUG("should not see any other type here"); + } + } + + /* + * Add tag objects and tagged blobs if they exist. + */ + if (tagged_blobs) { + if (tagged_blobs->oids.nr) { + const char *tagged_blob_path = "/tagged-blobs"; + tagged_blobs->type = OBJ_BLOB; + tagged_blobs->maybe_interesting = 1; + strmap_put(&ctx->paths_to_lists, tagged_blob_path, tagged_blobs); + push_to_stack(ctx, tagged_blob_path); + } else { + oid_array_clear(&tagged_blobs->oids); + free(tagged_blobs); + } + } + if (tags) { + if (tags->oids.nr) { + const char *tag_path = "/tags"; + tags->type = OBJ_TAG; + tags->maybe_interesting = 1; + strmap_put(&ctx->paths_to_lists, tag_path, tags); + push_to_stack(ctx, tag_path); + } else { + oid_array_clear(&tags->oids); + free(tags); + } + } + + return 0; +} + +/** + * Given the configuration of 'info', walk the commits based on 'info->revs' and + * call 'info->path_fn' on each discovered path. + * + * Returns nonzero on an error. + */ +int walk_objects_by_path(struct path_walk_info *info) +{ + int ret; + size_t commits_nr = 0, paths_nr = 0; + struct commit *c; + struct type_and_oid_list *root_tree_list; + struct type_and_oid_list *commit_list; + struct path_walk_context ctx = { + .repo = info->revs->repo, + .revs = info->revs, + .info = info, + .path_stack = { + .compare = compare_by_type, + .cb_data = &ctx + }, + .path_stack_pushed = STRSET_INIT, + .paths_to_lists = STRMAP_INIT + }; + + trace2_region_enter("path-walk", "commit-walk", info->revs->repo); + + CALLOC_ARRAY(commit_list, 1); + commit_list->type = OBJ_COMMIT; + + if (info->tags) + info->revs->tag_objects = 1; + + /* Insert a single list for the root tree into the paths. */ + CALLOC_ARRAY(root_tree_list, 1); + root_tree_list->type = OBJ_TREE; + root_tree_list->maybe_interesting = 1; + strmap_put(&ctx.paths_to_lists, root_path, root_tree_list); + push_to_stack(&ctx, root_path); + + /* + * Set these values before preparing the walk to catch + * lightweight tags pointing to non-commits and indexed objects. + */ + info->revs->blob_objects = info->blobs; + info->revs->tree_objects = info->trees; + + if (prepare_revision_walk(info->revs)) + die(_("failed to setup revision walk")); + + /* Walk trees to mark them as UNINTERESTING. */ + edge_repo = info->revs->repo; + edge_tree_list = root_tree_list; + mark_edges_uninteresting(info->revs, show_edge, + info->prune_all_uninteresting); + edge_repo = NULL; + edge_tree_list = NULL; + + info->revs->blob_objects = info->revs->tree_objects = 0; + + trace2_region_enter("path-walk", "pending-walk", info->revs->repo); + ret = setup_pending_objects(info, &ctx); + trace2_region_leave("path-walk", "pending-walk", info->revs->repo); + + if (ret) + return ret; + + while ((c = get_revision(info->revs))) { + struct object_id *oid; + struct tree *t; + commits_nr++; + + if (info->commits) + oid_array_append(&commit_list->oids, + &c->object.oid); + + /* If we only care about commits, then skip trees. */ + if (!info->trees && !info->blobs) + continue; + + oid = get_commit_tree_oid(c); + t = lookup_tree(info->revs->repo, oid); + + if (!t) { + error("could not find tree %s", oid_to_hex(oid)); + return -1; + } + + if (t->object.flags & SEEN) + continue; + t->object.flags |= SEEN; + oid_array_append(&root_tree_list->oids, oid); + } + + trace2_data_intmax("path-walk", ctx.repo, "commits", commits_nr); + trace2_region_leave("path-walk", "commit-walk", info->revs->repo); + + /* Track all commits. */ + if (info->commits && commit_list->oids.nr) + ret = info->path_fn("", &commit_list->oids, OBJ_COMMIT, + info->path_fn_data); + oid_array_clear(&commit_list->oids); + free(commit_list); + + trace2_region_enter("path-walk", "path-walk", info->revs->repo); + while (!ret && ctx.path_stack.nr) { + char *path = prio_queue_get(&ctx.path_stack); + paths_nr++; + + ret = walk_path(&ctx, path); + + free(path); + } + + /* Are there paths remaining? Likely they are from indexed objects. */ + if (!strmap_empty(&ctx.paths_to_lists)) { + struct hashmap_iter iter; + struct strmap_entry *entry; + + strmap_for_each_entry(&ctx.paths_to_lists, &iter, entry) + push_to_stack(&ctx, entry->key); + + while (!ret && ctx.path_stack.nr) { + char *path = prio_queue_get(&ctx.path_stack); + paths_nr++; + + ret = walk_path(&ctx, path); + + free(path); + } + } + + trace2_data_intmax("path-walk", ctx.repo, "paths", paths_nr); + trace2_region_leave("path-walk", "path-walk", info->revs->repo); + + clear_paths_to_lists(&ctx.paths_to_lists); + strset_clear(&ctx.path_stack_pushed); + clear_prio_queue(&ctx.path_stack); + return ret; +} + +void path_walk_info_init(struct path_walk_info *info) +{ + struct path_walk_info empty = PATH_WALK_INFO_INIT; + memcpy(info, &empty, sizeof(empty)); +} + +void path_walk_info_clear(struct path_walk_info *info) +{ + if (info->pl) { + clear_pattern_list(info->pl); + free(info->pl); + } +} diff --git a/path-walk.h b/path-walk.h new file mode 100644 index 0000000000..473ee9d361 --- /dev/null +++ b/path-walk.h @@ -0,0 +1,80 @@ +/* + * path-walk.h : Methods and structures for walking the object graph in batches + * by the paths that can reach those objects. + */ +#include "object.h" /* Required for 'enum object_type'. */ + +struct rev_info; +struct oid_array; +struct pattern_list; + +/** + * The type of a function pointer for the method that is called on a list of + * objects reachable at a given path. + */ +typedef int (*path_fn)(const char *path, + struct oid_array *oids, + enum object_type type, + void *data); + +struct path_walk_info { + /** + * revs provides the definitions for the commit walk, including + * which commits are UNINTERESTING or not. This structure is + * expected to be owned by the caller. + */ + struct rev_info *revs; + + /** + * The caller wishes to execute custom logic on objects reachable at a + * given path. Every reachable object will be visited exactly once, and + * the first path to see an object wins. This may not be a stable choice. + */ + path_fn path_fn; + void *path_fn_data; + + /** + * Initialize which object types the path_fn should be called on. This + * could also limit the walk to skip blobs if not set. + */ + int commits; + int trees; + int blobs; + int tags; + + /** + * When 'prune_all_uninteresting' is set and a path has all objects + * marked as UNINTERESTING, then the path-walk will not visit those + * objects. It will not call path_fn on those objects and will not + * walk the children of such trees. + */ + int prune_all_uninteresting; + + /** + * Specify a sparse-checkout definition to match our paths to. Do not + * walk outside of this sparse definition. If the patterns are in + * cone mode, then the search may prune directories that are outside + * of the cone. If not in cone mode, then all tree paths will be + * explored but the path_fn will only be called when the path matches + * the sparse-checkout patterns. + */ + struct pattern_list *pl; +}; + +#define PATH_WALK_INFO_INIT { \ + .blobs = 1, \ + .trees = 1, \ + .commits = 1, \ + .tags = 1, \ +} + +void path_walk_info_init(struct path_walk_info *info); +void path_walk_info_clear(struct path_walk_info *info); + +/** + * Given the configuration of 'info', walk the commits based on 'info->revs' and + * call 'info->path_fn' on each discovered path. + * + * Returns nonzero on an error. + */ +int walk_objects_by_path(struct path_walk_info *info); @@ -2,8 +2,6 @@ * Utilities for paths and pathnames */ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "abspath.h" #include "environment.h" @@ -30,7 +28,7 @@ static int get_st_mode_bits(const char *path, int *mode) return 0; } -struct strbuf *get_pathname(void) +static struct strbuf *get_pathname(void) { static struct strbuf pathname_array[4] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT @@ -387,10 +385,11 @@ void report_linked_checkout_garbage(struct repository *r) strbuf_release(&sb); } -static void adjust_git_path(const struct repository *repo, +static void adjust_git_path(struct repository *repo, struct strbuf *buf, int git_dir_len) { const char *base = buf->buf + git_dir_len; + if (is_dir_file(base, "info", "grafts")) strbuf_splice(buf, 0, buf->len, repo->graft_file, strlen(repo->graft_file)); @@ -399,8 +398,8 @@ static void adjust_git_path(const struct repository *repo, repo->index_file, strlen(repo->index_file)); else if (dir_prefix(base, "objects")) replace_dir(buf, git_dir_len + 7, repo->objects->odb->path); - else if (git_hooks_path && dir_prefix(base, "hooks")) - replace_dir(buf, git_dir_len + 5, git_hooks_path); + else if (repo_settings_get_hooks_path(repo) && dir_prefix(base, "hooks")) + replace_dir(buf, git_dir_len + 5, repo_settings_get_hooks_path(repo)); else if (repo->different_commondir) update_common_dir(buf, git_dir_len, repo->commondir); } @@ -414,12 +413,12 @@ static void strbuf_worktree_gitdir(struct strbuf *buf, else if (!wt->id) strbuf_addstr(buf, repo->commondir); else - strbuf_git_common_path(buf, repo, "worktrees/%s", wt->id); + repo_common_path_append(repo, buf, "worktrees/%s", wt->id); } -void repo_git_pathv(const struct repository *repo, - const struct worktree *wt, struct strbuf *buf, - const char *fmt, va_list args) +static void repo_git_pathv(struct repository *repo, + const struct worktree *wt, struct strbuf *buf, + const char *fmt, va_list args) { int gitdir_len; strbuf_worktree_gitdir(buf, repo, wt); @@ -432,7 +431,7 @@ void repo_git_pathv(const struct repository *repo, strbuf_cleanup_path(buf); } -char *repo_git_path(const struct repository *repo, +char *repo_git_path(struct repository *repo, const char *fmt, ...) { struct strbuf path = STRBUF_INIT; @@ -443,14 +442,27 @@ char *repo_git_path(const struct repository *repo, return strbuf_detach(&path, NULL); } -void strbuf_repo_git_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +const char *repo_git_path_append(struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) { va_list args; va_start(args, fmt); repo_git_pathv(repo, NULL, sb, fmt, args); va_end(args); + return sb->buf; +} + +const char *repo_git_path_replace(struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) +{ + va_list args; + strbuf_reset(sb); + va_start(args, fmt); + repo_git_pathv(repo, NULL, sb, fmt, args); + va_end(args); + return sb->buf; } char *mkpathdup(const char *fmt, ...) @@ -506,39 +518,56 @@ char *repo_worktree_path(const struct repository *repo, const char *fmt, ...) struct strbuf path = STRBUF_INIT; va_list args; + va_start(args, fmt); + do_worktree_path(repo, &path, fmt, args); + va_end(args); + + return strbuf_detach(&path, NULL); +} + +const char *repo_worktree_path_append(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) +{ + va_list args; + if (!repo->worktree) return NULL; va_start(args, fmt); - do_worktree_path(repo, &path, fmt, args); + do_worktree_path(repo, sb, fmt, args); va_end(args); - return strbuf_detach(&path, NULL); + return sb->buf; } -void strbuf_repo_worktree_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +const char *repo_worktree_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) { va_list args; + strbuf_reset(sb); if (!repo->worktree) - return; + return NULL; va_start(args, fmt); do_worktree_path(repo, sb, fmt, args); va_end(args); + + return sb->buf; } /* Returns 0 on success, negative on failure. */ -static int do_submodule_path(struct strbuf *buf, const char *path, +static int do_submodule_path(struct repository *repo, + struct strbuf *buf, const char *path, const char *fmt, va_list args) { struct strbuf git_submodule_common_dir = STRBUF_INIT; struct strbuf git_submodule_dir = STRBUF_INIT; int ret; - ret = submodule_to_gitdir(&git_submodule_dir, path); + ret = submodule_to_gitdir(repo, &git_submodule_dir, path); if (ret) goto cleanup; @@ -557,13 +586,14 @@ cleanup: return ret; } -char *git_pathdup_submodule(const char *path, const char *fmt, ...) +char *repo_submodule_path(struct repository *repo, + const char *path, const char *fmt, ...) { int err; va_list args; struct strbuf buf = STRBUF_INIT; va_start(args, fmt); - err = do_submodule_path(&buf, path, fmt, args); + err = do_submodule_path(repo, &buf, path, fmt, args); va_end(args); if (err) { strbuf_release(&buf); @@ -572,22 +602,41 @@ char *git_pathdup_submodule(const char *path, const char *fmt, ...) return strbuf_detach(&buf, NULL); } -int strbuf_git_path_submodule(struct strbuf *buf, const char *path, - const char *fmt, ...) +const char *repo_submodule_path_append(struct repository *repo, + struct strbuf *buf, + const char *path, + const char *fmt, ...) { int err; va_list args; va_start(args, fmt); - err = do_submodule_path(buf, path, fmt, args); + err = do_submodule_path(repo, buf, path, fmt, args); va_end(args); + if (err) + return NULL; + return buf->buf; +} - return err; +const char *repo_submodule_path_replace(struct repository *repo, + struct strbuf *buf, + const char *path, + const char *fmt, ...) +{ + int err; + va_list args; + strbuf_reset(buf); + va_start(args, fmt); + err = do_submodule_path(repo, buf, path, fmt, args); + va_end(args); + if (err) + return NULL; + return buf->buf; } -void repo_common_pathv(const struct repository *repo, - struct strbuf *sb, - const char *fmt, - va_list args) +static void repo_common_pathv(const struct repository *repo, + struct strbuf *sb, + const char *fmt, + va_list args) { strbuf_addstr(sb, repo->commondir); if (sb->len && !is_dir_sep(sb->buf[sb->len - 1])) @@ -596,14 +645,38 @@ void repo_common_pathv(const struct repository *repo, strbuf_cleanup_path(sb); } -void strbuf_git_common_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +char *repo_common_path(const struct repository *repo, + const char *fmt, ...) { + struct strbuf sb = STRBUF_INIT; va_list args; va_start(args, fmt); + repo_common_pathv(repo, &sb, fmt, args); + va_end(args); + return strbuf_detach(&sb, NULL); +} + +const char *repo_common_path_append(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + repo_common_pathv(repo, sb, fmt, args); + va_end(args); + return sb->buf; +} + +const char *repo_common_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) +{ + va_list args; + strbuf_reset(sb); + va_start(args, fmt); repo_common_pathv(repo, sb, fmt, args); va_end(args); + return sb->buf; } static struct passwd *getpw_str(const char *username, size_t len) @@ -765,21 +838,22 @@ const char *enter_repo(const char *path, unsigned flags) return NULL; } -int calc_shared_perm(int mode) +int calc_shared_perm(struct repository *repo, + int mode) { int tweak; - if (get_shared_repository() < 0) - tweak = -get_shared_repository(); + if (repo_settings_get_shared_repository(repo) < 0) + tweak = -repo_settings_get_shared_repository(repo); else - tweak = get_shared_repository(); + tweak = repo_settings_get_shared_repository(repo); if (!(mode & S_IWUSR)) tweak &= ~0222; if (mode & S_IXUSR) /* Copy read bits to execute bits */ tweak |= (tweak & 0444) >> 2; - if (get_shared_repository() < 0) + if (repo_settings_get_shared_repository(repo) < 0) mode = (mode & ~0777) | tweak; else mode |= tweak; @@ -787,17 +861,17 @@ int calc_shared_perm(int mode) return mode; } - -int adjust_shared_perm(const char *path) +int adjust_shared_perm(struct repository *repo, + const char *path) { int old_mode, new_mode; - if (!get_shared_repository()) + if (!repo_settings_get_shared_repository(repo)) return 0; if (get_st_mode_bits(path, &old_mode) < 0) return -1; - new_mode = calc_shared_perm(old_mode); + new_mode = calc_shared_perm(repo, old_mode); if (S_ISDIR(old_mode)) { /* Copy read bits to execute bits */ new_mode |= (new_mode & 0444) >> 2; @@ -816,7 +890,7 @@ int adjust_shared_perm(const char *path) return 0; } -void safe_create_dir(const char *dir, int share) +void safe_create_dir(struct repository *repo, const char *dir, int share) { if (mkdir(dir, 0777) < 0) { if (errno != EEXIST) { @@ -824,7 +898,7 @@ void safe_create_dir(const char *dir, int share) exit(1); } } - else if (share && adjust_shared_perm(dir)) + else if (share && adjust_shared_perm(repo, dir)) die(_("Could not make %s writable by group"), dir); } @@ -25,22 +25,20 @@ char *mkpathdup(const char *fmt, ...) __attribute__((format (printf, 1, 2))); /* - * The `strbuf_git_common_path` family of functions will construct a path into a + * The `repo_common_path` family of functions will construct a path into a * repository's common git directory, which is shared by all worktrees. */ - -/* - * Constructs a path into the common git directory of repository `repo` and - * append it in the provided buffer `sb`. - */ -void strbuf_git_common_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +char *repo_common_path(const struct repository *repo, + const char *fmt, ...) + __attribute__((format (printf, 2, 3))); +const char *repo_common_path_append(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) + __attribute__((format (printf, 3, 4))); +const char *repo_common_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) __attribute__((format (printf, 3, 4))); -void repo_common_pathv(const struct repository *repo, - struct strbuf *buf, - const char *fmt, - va_list args); /* * The `repo_git_path` family of functions will construct a path into a repository's @@ -54,29 +52,16 @@ void repo_common_pathv(const struct repository *repo, * For an exhaustive list of the adjustments made look at `common_list` and * `adjust_git_path` in path.c. */ - -/* - * Return a path into the git directory of repository `repo`. - */ -char *repo_git_path(const struct repository *repo, +char *repo_git_path(struct repository *repo, const char *fmt, ...) __attribute__((format (printf, 2, 3))); - -/* - * Print a path into the git directory of repository `repo` into the provided - * buffer. - */ -void repo_git_pathv(const struct repository *repo, - const struct worktree *wt, struct strbuf *buf, - const char *fmt, va_list args); - -/* - * Construct a path into the git directory of repository `repo` and append it - * to the provided buffer `sb`. - */ -void strbuf_repo_git_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +const char *repo_git_path_append(struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) + __attribute__((format (printf, 3, 4))); +const char *repo_git_path_replace(struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) __attribute__((format (printf, 3, 4))); /* @@ -90,40 +75,44 @@ const char *worktree_git_path(struct repository *r, __attribute__((format (printf, 3, 4))); /* - * Return a path into the worktree of repository `repo`. + * The `repo_worktree_path` family of functions will construct a path into a + * repository's worktree. * - * If the repository doesn't have a worktree NULL is returned. + * Returns a `NULL` pointer in case the repository has no worktree. */ char *repo_worktree_path(const struct repository *repo, const char *fmt, ...) __attribute__((format (printf, 2, 3))); - -/* - * Construct a path into the worktree of repository `repo` and append it - * to the provided buffer `sb`. - * - * If the repository doesn't have a worktree nothing will be appended to `sb`. - */ -void strbuf_repo_worktree_path(struct strbuf *sb, - const struct repository *repo, +const char *repo_worktree_path_append(const struct repository *repo, + struct strbuf *sb, const char *fmt, ...) __attribute__((format (printf, 3, 4))); +const char *repo_worktree_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) + __attribute__((format (printf, 3, 4))); /* - * Return a path into a submodule's git directory located at `path`. `path` - * must only reference a submodule of the main repository (the_repository). - */ -char *git_pathdup_submodule(const char *path, const char *fmt, ...) - __attribute__((format (printf, 2, 3))); - -/* - * Construct a path into a submodule's git directory located at `path` and - * append it to the provided buffer `sb`. `path` must only reference a - * submodule of the main repository (the_repository). + * The `repo_submodule_path` family of functions will construct a path into a + * submodule's git directory located at `path`. `path` must be a submodule path + * as found in the index and must be part of the given repository. + * + * Returns a `NULL` pointer in case the submodule cannot be found. */ -int strbuf_git_path_submodule(struct strbuf *sb, const char *path, - const char *fmt, ...) +char *repo_submodule_path(struct repository *repo, + const char *path, + const char *fmt, ...) __attribute__((format (printf, 3, 4))); +const char *repo_submodule_path_append(struct repository *repo, + struct strbuf *sb, + const char *path, + const char *fmt, ...) + __attribute__((format (printf, 4, 5))); +const char *repo_submodule_path_replace(struct repository *repo, + struct strbuf *sb, + const char *path, + const char *fmt, ...) + __attribute__((format (printf, 4, 5))); void report_linked_checkout_garbage(struct repository *r); @@ -152,8 +141,8 @@ const char *git_path_shallow(struct repository *r); int ends_with_path_components(const char *path, const char *components); -int calc_shared_perm(int mode); -int adjust_shared_perm(const char *path); +int calc_shared_perm(struct repository *repo, int mode); +int adjust_shared_perm(struct repository *repo, const char *path); char *interpolate_path(const char *path, int real_home); @@ -230,101 +219,21 @@ char *xdg_cache_home(const char *filename); * directories under $GIT_DIR. Don't use it for working tree * directories. */ -void safe_create_dir(const char *dir, int share); - -/* - * Do not use this function. It is only exported to other subsystems until we - * can get rid of the below block of functions that implicitly rely on - * `the_repository`. - */ -struct strbuf *get_pathname(void); +void safe_create_dir(struct repository *repo, const char *dir, int share); # ifdef USE_THE_REPOSITORY_VARIABLE # include "strbuf.h" # include "repository.h" -/* - * Return a statically allocated path into the main repository's - * (the_repository) common git directory. - */ -__attribute__((format (printf, 1, 2))) -static inline const char *git_common_path(const char *fmt, ...) -{ - struct strbuf *pathname = get_pathname(); - va_list args; - va_start(args, fmt); - repo_common_pathv(the_repository, pathname, fmt, args); - va_end(args); - return pathname->buf; -} - -/* - * Construct a path into the main repository's (the_repository) git directory - * and place it in the provided buffer `buf`, the contents of the buffer will - * be overridden. - */ -__attribute__((format (printf, 2, 3))) -static inline char *git_path_buf(struct strbuf *buf, const char *fmt, ...) -{ - va_list args; - strbuf_reset(buf); - va_start(args, fmt); - repo_git_pathv(the_repository, NULL, buf, fmt, args); - va_end(args); - return buf->buf; -} - -/* - * Construct a path into the main repository's (the_repository) git directory - * and append it to the provided buffer `sb`. - */ -__attribute__((format (printf, 2, 3))) -static inline void strbuf_git_path(struct strbuf *sb, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - repo_git_pathv(the_repository, NULL, sb, fmt, args); - va_end(args); -} - -/* - * Return a statically allocated path into the main repository's - * (the_repository) git directory. - */ -__attribute__((format (printf, 1, 2))) -static inline const char *git_path(const char *fmt, ...) -{ - struct strbuf *pathname = get_pathname(); - va_list args; - va_start(args, fmt); - repo_git_pathv(the_repository, NULL, pathname, fmt, args); - va_end(args); - return pathname->buf; -} - #define GIT_PATH_FUNC(func, filename) \ const char *func(void) \ { \ static char *ret; \ if (!ret) \ - ret = git_pathdup(filename); \ + ret = repo_git_path(the_repository, filename); \ return ret; \ } -/* - * Return a path into the main repository's (the_repository) git directory. - */ -__attribute__((format (printf, 1, 2))) -static inline char *git_pathdup(const char *fmt, ...) -{ - struct strbuf path = STRBUF_INIT; - va_list args; - va_start(args, fmt); - repo_git_pathv(the_repository, NULL, &path, fmt, args); - va_end(args); - return strbuf_detach(&path, NULL); -} - # endif /* USE_THE_REPOSITORY_VARIABLE */ #endif /* PATH_H */ @@ -1,7 +1,7 @@ # Bulgarian translation of git po-file. -# Copyright (C) 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 Alexander Shopov <ash@kambanaria.org>. +# Copyright (C) 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025 Alexander Shopov <ash@kambanaria.org>. # This file is distributed under the same license as the git package. -# Alexander Shopov <ash@kambanaria.org>, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. +# Alexander Shopov <ash@kambanaria.org>, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025. # ======================== # DICTIONARY TO MERGE IN GIT GUI # ------------------------ @@ -233,6 +233,7 @@ # cache-tree кеша на обектите-дървета # acquire lock придобивам ключалка # detached отделѐн, несвързан +# revision walk обхождане на версиите # # ------------------------ # „$var“ - може да не сработва за shell има gettext и eval_gettext - проверка - намират се лесно по „$ @@ -261,8 +262,8 @@ msgid "" msgstr "" "Project-Id-Version: git 2.48\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-27 22:37+0100\n" -"PO-Revision-Date: 2024-12-27 22:40+0100\n" +"POT-Creation-Date: 2025-03-05 22:57+0000\n" +"PO-Revision-Date: 2025-03-06 09:15+0100\n" "Last-Translator: Alexander Shopov <ash@kambanaria.org>\n" "Language-Team: Bulgarian <dict@fsa-bg.org>\n" "Language: bg\n" @@ -2655,6 +2656,18 @@ msgstr "git archive: протоколна грешка" msgid "git archive: expected a flush" msgstr "git archive: очакваше се изчистване на буферите чрез „flush“" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=БРОЙ] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "проблем при зареждане на частично хранилище" + +msgid "Minimum number of objects to request at a time" +msgstr "Минимален БРОЙ обекти заявявани наведнъж" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Ограничаване на липсващите обекти до текущото частично хранилище" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -3434,10 +3447,6 @@ msgstr "" msgid "git version:\n" msgstr "версия на git:\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "грешка при изпълнението на „uname()“ — „%s“ (%d)\n" - msgid "compiler info: " msgstr "компилатор: " @@ -4466,8 +4475,98 @@ msgstr "" "Настройката „clean.requireForce“ е зададена, което изисква опцията „-f“. " "Няма да се извърши изчистване" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [ОПЦИЯ…] [--] ХРАНИЛИЩЕ [ДИРЕКТОРИЯ]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "" +"ПРЕДУПРЕЖДЕНИЕ: не може да се добави алтернативен източник на „%s“: %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "не може да бъде получена информация чрез „stat“ за „%s“" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "„%s“ съществува и не е директория" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "„%s“ е символна връзка, не може да се клонира с опцията „--local“" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "неуспешно итериране по „%s“" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "" +"символната връзка „%s“ съществува, не може да се клонира с опцията „--local“" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "неуспешно изтриване на „%s“" + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "твърдата връзка не може да се провери при „%s“" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "твърдата връзка е различна от източника „%s“" + +#, c-format +msgid "failed to create link '%s'" +msgstr "връзката „%s“ не може да бъде създадена" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "файлът не може да бъде копиран като „%s“" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "неуспешно итериране по „%s“" + +#, c-format +msgid "done.\n" +msgstr "действието завърши.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Клонирането бе успешно за разлика от подготовката на работното дърво\n" +"за определен клон. Все пак може да проверите кои файлове и от кой\n" +"клон в момента са изтеглени с командата „git status“. Може да\n" +"завършите изтеглянето на клона с командата:\n" +"\n" +" git restore --source=HEAD :/\n" + +msgid "remote did not send all necessary objects" +msgstr "отдалеченото хранилище не изпрати всички необходими обекти." + +#, c-format +msgid "unable to update %s" +msgstr "обектът „%s“ не може да бъде обновен" + +msgid "failed to initialize sparse-checkout" +msgstr "частичното изтегляне не може да се инициализира" + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "" +"указателят „HEAD“ от отдалеченото хранилище сочи към нещо, което не " +"съществува. Изтегляне не може да се извърши" + +msgid "unable to checkout working tree" +msgstr "работното дърво не може да бъде подготвено" + +msgid "unable to write parameters to config file" +msgstr "настройките не може да бъдат записани в конфигурационния файл" + +msgid "cannot repack to clean up" +msgstr "не може да се извърши пакетиране за изчистване на файловете" + +msgid "cannot unlink temporary alternates file" +msgstr "временният файл за алтернативни обекти не може да бъде изтрит" msgid "don't clone shallow repository" msgstr "без клониране на плитко хранилище" @@ -4521,6 +4620,9 @@ msgstr "използване на това ИМЕ вместо „origin“ пр msgid "checkout <branch> instead of the remote's HEAD" msgstr "изтегляне на този КЛОН, а не соченият от отдалечения указател „HEAD“" +msgid "clone single revision <rev> and check out" +msgstr "клониране на единствена ВЕРСИЯ и изтегляне в работната директория" + msgid "path to git-upload-pack on the remote" msgstr "път към командата „git-upload-pack“ на отдалеченото хранилище" @@ -4544,9 +4646,8 @@ msgstr "" "клониране само на един клон — или сочения от отдалечения „HEAD“, или изрично " "зададения с „--branch“" -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "" -"без клониране на етикети, като последващите доставяния няма да ги следят" +msgid "clone tags, and make later fetches not to follow them" +msgstr "клониране на етикети, като последващите доставяния няма да ги следят" msgid "any cloned submodules will be shallow" msgstr "всички клонирани подмодули ще са плитки" @@ -4590,104 +4691,8 @@ msgid "a URI for downloading bundles before fetching from origin remote" msgstr "" "АДРЕС за доставяне на пратки на git преди доставяне от отдалеченото хранилище" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "" -"ПРЕДУПРЕЖДЕНИЕ: не може да се добави алтернативен източник на „%s“: %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "не може да бъде получена информация чрез „stat“ за „%s“" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "„%s“ съществува и не е директория" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "„%s“ е символна връзка, не може да се клонира с опцията „--local“" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "неуспешно итериране по „%s“" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "" -"символната връзка „%s“ съществува, не може да се клонира с опцията „--local“" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "неуспешно изтриване на „%s“" - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "твърдата връзка не може да се провери при „%s“" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "твърдата връзка е различна от източника „%s“" - -#, c-format -msgid "failed to create link '%s'" -msgstr "връзката „%s“ не може да бъде създадена" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "файлът не може да бъде копиран като „%s“" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "неуспешно итериране по „%s“" - -#, c-format -msgid "done.\n" -msgstr "действието завърши.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Клонирането бе успешно за разлика от подготовката на работното дърво\n" -"за определен клон. Все пак може да проверите кои файлове и от кой\n" -"клон в момента са изтеглени с командата „git status“. Може да\n" -"завършите изтеглянето на клона с командата:\n" -"\n" -" git restore --source=HEAD :/\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "" -"Клонът „%s“ от отдалеченото хранилище, което клонирате,\n" -"и който следва да бъде изтеглен, не съществува." - -msgid "remote did not send all necessary objects" -msgstr "отдалеченото хранилище не изпрати всички необходими обекти." - -#, c-format -msgid "unable to update %s" -msgstr "обектът „%s“ не може да бъде обновен" - -msgid "failed to initialize sparse-checkout" -msgstr "частичното изтегляне не може да се инициализира" - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "" -"указателят „HEAD“ от отдалеченото хранилище сочи към нещо, което не " -"съществува. Изтегляне не може да се извърши" - -msgid "unable to checkout working tree" -msgstr "работното дърво не може да бъде подготвено" - -msgid "unable to write parameters to config file" -msgstr "настройките не може да бъдат записани в конфигурационния файл" - -msgid "cannot repack to clean up" -msgstr "не може да се извърши пакетиране за изчистване на файловете" - -msgid "cannot unlink temporary alternates file" -msgstr "временният файл за алтернативни обекти не може да бъде изтрит" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [ОПЦИЯ…] [--] ХРАНИЛИЩЕ [ДИРЕКТОРИЯ]" msgid "Too many arguments." msgstr "Прекалено много аргументи." @@ -4796,6 +4801,10 @@ msgstr "отдалеченият транспорт върна грешка" msgid "Remote branch %s not found in upstream %s" msgstr "Отдалеченият клон „%s“ липсва в клонираното хранилище „%s“" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Отдалечената версия „%s“ липсва в клонираното хранилище „%s“" + msgid "You appear to have cloned an empty repository." msgstr "Изглежда клонирахте празно хранилище." @@ -4975,7 +4984,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree: не може да се прочете" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -4985,7 +4994,7 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a|--interactive|--patch] [-s] [-v] [-u РЕЖИМ] [--amend]\n" +"git commit [-a|--interactive|--patch] [-s] [-v] [-u[РЕЖИМ]] [--amend]\n" " [--dry-run] [(-c|-C|--squash) ПОДАВАНЕ |--fixup [(amend|" "reword):]ПОДАВАНЕ]\n" " [-F ФАЙЛ|-m СЪОБЩЕНИЕ] [--reset-author] [--allow-empty]\n" @@ -6424,8 +6433,8 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Изпълнете\n" "\n" @@ -6435,7 +6444,7 @@ msgstr "" "„remote.%s.followRemoteHEAD, ако не искате тези съобщения.\n" "Изпълнението на\n" "\n" -" git config set remote.%s.followRemoteHEAD %s\n" +" git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s\n" "\n" "ще изключи предупреждението, докато отдалеченият указател HEAD не\n" "започне да сочи нещо друго." @@ -7124,6 +7133,9 @@ msgstr "" msgid "repack all other packs except the largest pack" msgstr "препакетиране на всичко без най-големия пакет" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "префикс на имената на пакетите за окастрени обекти" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "неразпозната стойност на „gc.logExpiry“ %s" @@ -7944,6 +7956,10 @@ msgid "Cannot come back to cwd" msgstr "Процесът не може да се върне към предишната работна директория" #, c-format +msgid "bad --pack_header: %s" +msgstr "неправилна стойност за „--pack_header“: „%s“" + +#, c-format msgid "bad %s" msgstr "неправилна стойност „%s“" @@ -8835,10 +8851,6 @@ msgstr "непозната опция за стратегия: -X%s" msgid "malformed input line: '%s'." msgstr "входен ред с неправилен формат: „%s“." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "сливането не може да продължи — %d-тото завърши с грешка" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [ОПЦИЯ…] [ПОДАВАНЕ…]" @@ -9685,6 +9697,13 @@ msgstr "" "СПИСЪК_С_ОБЕКТИ]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "неправилна опция „--name-hash-version“: %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "текущо опцията „--write-bitmap-index“ изисква „--name-hash-version=1“" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -10025,6 +10044,11 @@ msgstr "протокол" msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "без ползване на настройки „uploadpack.blobpackfileuri“ с този протокол" +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"използване на указаната функция за контролни суми за групиране на подобните " +"обекти" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "веригата с разлики е прекалено дълбока — %d, ще се ползва %d" @@ -11304,8 +11328,8 @@ msgstr "не е указан журнал с подавания за изтри msgid "invalid ref format: %s" msgstr "неправилен формат на указател: %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=ФОРМАТ [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=ФОРМАТ [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -11316,6 +11340,9 @@ msgstr "указване на форма̀та за указател, към к msgid "perform a non-destructive dry-run" msgstr "пробно изпълнение — без промяна на данни" +msgid "drop reflogs entirely during the migration" +msgstr "журналът на указателите да се изтрие изцяло по време на миграцията" + msgid "missing --ref-format=<format>" msgstr "липсва опцията --ref-format=ФОРМАТ" @@ -11786,8 +11813,14 @@ msgstr "Никой от адресите, които не са за изтлас msgid "be verbose; must be placed before a subcommand" msgstr "повече подробности. Поставя се пред подкоманда" -msgid "git repack [<options>]" -msgstr "git repack [ОПЦИЯ…]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=БРОЙ] [--depth=БРОЙ] [--threads=БРОЙ] [--keep-pack=ИМЕ_НА_ПАКЕТ]\n" +"[--write-midx] [--name-hash-version=БРОЙ]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11875,6 +11908,11 @@ msgid "pass --no-reuse-object to git-pack-objects" msgstr "" "подаване на опцията „--no-reuse-object“ на командата „git-pack-objects“" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"укажете функция за контролни суми за групиране на подобните обекти по път" + msgid "do not run git-update-server-info" msgstr "без изпълнение на командата „git-update-server-info“" @@ -11927,9 +11965,6 @@ msgstr "откриване на геометрична прогресия с ч msgid "write a multi-pack index of the resulting packs" msgstr "запазване на многопакетен индекс за създадените пакети" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "префикс на имената на пакетите за окастрени обекти" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "префикс на имената на пакетите за филтрирани обекти" @@ -12146,9 +12181,6 @@ msgstr "опцията „-l“ приема точно един шаблон" msgid "need some commits to replay" msgstr "необходимо е да има подавания за прилагане отново" -msgid "--onto and --advance are incompatible" -msgstr "опциите „--onto“ и „--advance“ са несъвместими" - msgid "all positive revisions given must be references" msgstr "всички зададени положителни версии трябва да са указатели" @@ -14852,6 +14884,9 @@ msgstr "Внасяне на хранилище на GNU Arch в Git" msgid "Create an archive of files from a named tree" msgstr "Създаване на архив с файловете от именовано дърво" +msgid "Download missing objects in a partial clone" +msgstr "Изтегляне на липсващите обекти в частично хранилище" + msgid "Use binary search to find the commit that introduced a bug" msgstr "Двоично търсене на промяната, която е причинила грешка" @@ -16852,6 +16887,12 @@ msgstr "неправилен аргумент към „%s“" msgid "invalid regex given to -I: '%s'" msgstr "неправилен регулярен израз подаден към „-I“: „%s“" +msgid "-G requires a non-empty argument" +msgstr "опцията „-G“ изисква аргумент" + +msgid "-S requires a non-empty argument" +msgstr "опцията „-S“ изисква аргумент" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "неразпознат параметър към опцията „--submodule“: „%s“" @@ -19123,6 +19164,10 @@ msgid "unable to write file %s" msgstr "файлът „%s“ не може да бъде записан" #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "смаляващият се файл „%s“ не може да бъде записван" + +#, c-format msgid "unable to set permission to '%s'" msgstr "права̀та за достъп до „%s“ не може да бъдат зададени" @@ -19722,6 +19767,52 @@ msgstr "непознат флаг „%c“" msgid "unknown non-ascii option in string: `%s'" msgstr "непозната стойност извън „ascii“ в низа: „%s“" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=%s]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[%s]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " %s" + msgid "..." msgstr "…" @@ -19809,6 +19900,21 @@ msgid "failed to parse %s" msgstr "„%s“ не може да бъде анализиран" #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "неуспешно обхождане на дъщерните елементи на дървото „%s“: то липсва" + +#, c-format +msgid "failed to find object %s" +msgstr "обектът „%s“ липсва" + +#, c-format +msgid "failed to find tag %s" +msgstr "етикетът „%s“ липсва" + +msgid "failed to setup revision walk" +msgstr "неуспешно настройване на обхождането на версиите" + +#, c-format msgid "Could not make %s writable by group" msgstr "Не може да се дадат права̀ за запис в директорията „%s“ на групата" @@ -19957,6 +20063,22 @@ msgstr "" msgid "could not fetch %s from promisor remote" msgstr "„%s“ не може да се достави от гарантиращото хранилище" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "има хранилище с име „%s“, но адресът му сочи към „%s“, а не към „%s“" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "непозната стойност „%s“ за настройката „%s“" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "непознат елемент „%s“ в информацията за отдалеченото хранилище" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "липсва приетото вече хранилище-гарант „%s“" + msgid "object-info: expected flush after arguments" msgstr "object-info: след аргументите се очаква изчистване на буферите" @@ -20803,6 +20925,14 @@ msgid "invalid refspec '%s'" msgstr "неправилен указател: „%s“" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "шаблонът „%s“ не съдържа „*“" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "заместителят „%s“ не съдържа „*“" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "" "неправилно екраниране или цитиране в стойността към опция за изтласкване: " @@ -20930,6 +21060,28 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: непозната команда „%s“ от git" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"изчитането на отдалеченото хранилище от „%s/%s“ предстои да бъде " +"премахнато.\n" +"Ако все още ползвате директорията „remotes/“, препоръчваме да я мигрирате\n" +"към следящи директории на база настройки чрез командата:\n" +"\n" +" git remote rename %s %s\n" +"\n" +"Ако не може поради някаква причина, молим да ни известите за нея с\n" +"е-писмо до пощенския списък: <git@vger.kernel.org>." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "" "съкращението за отдалечено хранилище не може за започва със знака „/“: %s" @@ -20965,14 +21117,6 @@ msgid "%s tracks both %s and %s" msgstr "„%s“ следи както „%s“, така и „%s“" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "ключ „%s“ на шаблона не съдържа „*“" - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "стойност „%s“ на шаблона не съдържа „*“" - -#, c-format msgid "src refspec %s does not match any" msgstr "указателят на версия-източник „%s“ не съвпада с никой обект" @@ -22945,6 +23089,28 @@ msgstr "" "какъв брой записи в кеша на обектите-дървета да се отбележат като невалидни " "(стандартно е 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk ОПЦИЯ… -- ОПЦИЯ_ЗА_ВЕРСИИ…" + +msgid "toggle inclusion of blob objects" +msgstr "превключване на поместването на обекти-BLOB" + +msgid "toggle inclusion of commit objects" +msgstr "превключване на поместването на обекти-подавания" + +msgid "toggle inclusion of tag objects" +msgstr "превключване на поместването на обекти-етикети" + +msgid "toggle inclusion of tree objects" +msgstr "превключване на поместването на обекти-дърво" + +msgid "toggle pruning of uninteresting paths" +msgstr "" +"превключване на окастрянето на пътищата, които не представляват интерес" + +msgid "read a pattern list over stdin" +msgstr "изчитане на списък с шаблони от стандартния вход" + #, c-format msgid "commit %s is not marked reachable" msgstr "подаването „%s“ не е отбелязано като достижимо" @@ -23581,6 +23747,10 @@ msgstr "грешка: " msgid "warning: " msgstr "предупреждение: " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "грешка при изпълнението на „uname()“ — „%s“ (%d)\n" + msgid "Fetching objects" msgstr "Доставяне на обектите" @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-20 17:44+0100\n" -"PO-Revision-Date: 2024-12-27 16:43+0100\n" +"POT-Creation-Date: 2025-03-06 18:29+0100\n" +"PO-Revision-Date: 2025-03-07 17:28+0100\n" "Last-Translator: Ralf Thielow <ralf.thielow@gmail.com>\n" "Language-Team: German\n" "Language: de\n" @@ -2400,6 +2400,18 @@ msgstr "git archive: Protokollfehler" msgid "git archive: expected a flush" msgstr "git archive: erwartete eine Spülung (flush)" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "Problem beim Laden von sparse-checkout" + +msgid "Minimum number of objects to request at a time" +msgstr "Mindestanzahl der gleichzeitig anzufordernden Objekte" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "fehlenden Objekte im aktuellen sparse-checkout beschränken" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -3167,10 +3179,6 @@ msgstr "" msgid "git version:\n" msgstr "git Version:\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() ist fehlgeschlagen mit Fehler '%s' (%d)\n" - msgid "compiler info: " msgstr "Compiler Info: " @@ -4201,8 +4209,95 @@ msgstr "" "clean.requireForce ist 'true' und -f ist nicht angegeben: clean wird " "verweigert" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<Optionen>] [--] <Repository> [<Verzeichnis>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: Konnte Alternative für '%s' nicht hinzufügen: %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "Konnte '%s' nicht lesen" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s existiert und ist kein Verzeichnis" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "" +"'%s' ist eine symbolische Verknüpfung, verweigere das Klonen mit --local" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "Fehler beim Starten der Iteration über '%s'" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "" +"symbolische Verknüpfung '%s' existiert, verweigere das Klonen mit --local" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "Konnte '%s' nicht entfernen." + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "Hardlink bei '%s' kann nicht geprüft werden" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "Hardlink unterscheidet sich von der Quelle bei '%s'" + +#, c-format +msgid "failed to create link '%s'" +msgstr "Konnte Verweis '%s' nicht erstellen" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "Konnte Datei nicht nach '%s' kopieren" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "Fehler beim Iterieren über '%s'" + +#, c-format +msgid "done.\n" +msgstr "Fertig.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Klonen erfolgreich, Auschecken ist aber fehlgeschlagen.\n" +"Sie können mit 'git status' prüfen, was ausgecheckt worden ist\n" +"und das Auschecken mit 'git restore --source=HEAD :/' erneut versuchen.\n" + +msgid "remote did not send all necessary objects" +msgstr "Remote-Repository hat nicht alle erforderlichen Objekte gesendet" + +#, c-format +msgid "unable to update %s" +msgstr "kann %s nicht aktualisieren" + +msgid "failed to initialize sparse-checkout" +msgstr "Fehler beim Initialisieren vom partiellen Checkout." + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "" +"HEAD des Remote-Repositories verweist auf nicht existierende Referenz, kann " +"nicht ausgecheckt werden" + +msgid "unable to checkout working tree" +msgstr "Arbeitsverzeichnis konnte nicht ausgecheckt werden" + +msgid "unable to write parameters to config file" +msgstr "konnte Parameter nicht in Konfigurationsdatei schreiben" + +msgid "cannot repack to clean up" +msgstr "Kann \"repack\" zum Aufräumen nicht aufrufen" + +msgid "cannot unlink temporary alternates file" +msgstr "Kann temporäre \"alternates\"-Datei nicht entfernen" msgid "don't clone shallow repository" msgstr "Repository mit unvollständiger Historie nicht klonen" @@ -4255,6 +4350,9 @@ msgstr "<Name> statt 'origin' für Upstream-Repository verwenden" msgid "checkout <branch> instead of the remote's HEAD" msgstr "<Branch> auschecken, anstatt HEAD des Remote-Repositories" +msgid "clone single revision <rev> and check out" +msgstr "einzelnen Commit <Commit> klonen und auschecken" + msgid "path to git-upload-pack on the remote" msgstr "Pfad zu \"git-upload-pack\" auf der Gegenseite" @@ -4280,8 +4378,8 @@ msgstr "Historie eines flachen Klons vertiefen, Referenz exkludiert" msgid "clone only one branch, HEAD or --branch" msgstr "nur einen Branch klonen, HEAD oder --branch" -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "keine Tags klonen, und auch bei späteren Abrufen nicht beachten" +msgid "clone tags, and make later fetches not to follow them" +msgstr "Tags klonen und dafür sorgen, dass spätere Abrufe ihnen nicht folgen" msgid "any cloned submodules will be shallow" msgstr "jedes geklonte Submodul mit unvollständiger Historie (shallow)" @@ -4326,99 +4424,8 @@ msgstr "" "eine URI für das Herunterladen von Bundles vor dem Abruf\n" "aus dem ursprünglichen Remote-Repository" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info: Konnte Alternative für '%s' nicht hinzufügen: %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "Konnte '%s' nicht lesen" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s existiert und ist kein Verzeichnis" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "" -"'%s' ist eine symbolische Verknüpfung, verweigere das Klonen mit --local" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "Fehler beim Starten der Iteration über '%s'" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "" -"symbolische Verknüpfung '%s' existiert, verweigere das Klonen mit --local" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "Konnte '%s' nicht entfernen." - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "Hardlink bei '%s' kann nicht geprüft werden" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "Hardlink unterscheidet sich von der Quelle bei '%s'" - -#, c-format -msgid "failed to create link '%s'" -msgstr "Konnte Verweis '%s' nicht erstellen" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "Konnte Datei nicht nach '%s' kopieren" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "Fehler beim Iterieren über '%s'" - -#, c-format -msgid "done.\n" -msgstr "Fertig.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Klonen erfolgreich, Auschecken ist aber fehlgeschlagen.\n" -"Sie können mit 'git status' prüfen, was ausgecheckt worden ist\n" -"und das Auschecken mit 'git restore --source=HEAD :/' erneut versuchen.\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Konnte zu klonenden Remote-Branch %s nicht finden." - -msgid "remote did not send all necessary objects" -msgstr "Remote-Repository hat nicht alle erforderlichen Objekte gesendet" - -#, c-format -msgid "unable to update %s" -msgstr "kann %s nicht aktualisieren" - -msgid "failed to initialize sparse-checkout" -msgstr "Fehler beim Initialisieren vom partiellen Checkout." - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "" -"HEAD des Remote-Repositories verweist auf nicht existierende Referenz, kann " -"nicht ausgecheckt werden" - -msgid "unable to checkout working tree" -msgstr "Arbeitsverzeichnis konnte nicht ausgecheckt werden" - -msgid "unable to write parameters to config file" -msgstr "konnte Parameter nicht in Konfigurationsdatei schreiben" - -msgid "cannot repack to clean up" -msgstr "Kann \"repack\" zum Aufräumen nicht aufrufen" - -msgid "cannot unlink temporary alternates file" -msgstr "Kann temporäre \"alternates\"-Datei nicht entfernen" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<Optionen>] [--] <Repository> [<Verzeichnis>]" msgid "Too many arguments." msgstr "Zu viele Argumente." @@ -4531,6 +4538,10 @@ msgstr "Remoteübertragung meldete Fehler" msgid "Remote branch %s not found in upstream %s" msgstr "Remote-Branch %s nicht im Upstream-Repository %s gefunden" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Remote-Commit %s nicht im Upstream-Repository %s gefunden" + msgid "You appear to have cloned an empty repository." msgstr "Sie scheinen ein leeres Repository geklont zu haben." @@ -4710,7 +4721,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree: Fehler beim Lesen" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -4720,14 +4731,14 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<Modus>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<Modus>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <Commit> | --fixup [(amend|" "reword):]<Commit>]\n" " [-F <Datei> | -m <Nachricht>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<Autor>]\n" " [--date=<Datum>] [--cleanup=<Modus>] [--[no-]status]\n" " [-i | -o] [--pathspec-from-file=<Datei> [--pathspec-file-nul]]\n" -" [(--trailer <Token>[(=|:)<Wert>])...] [-S[<Key-Id>]]\n" +" [(--trailer <Token>[(=|:)<Wert>])...] [-S[<Key-ID>>]]\n" " [--] [<Pfadspezifikation>...]" msgid "git status [<options>] [--] [<pathspec>...]" @@ -6139,14 +6150,15 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Führen Sie 'git remote set-head %s %s' aus, um der Änderung zu folgen,\n" "oder setzen Sie die Konfiguration 'remote.%s.followRemoteHEAD' auf einen\n" -"anderen Wert, wenn Sie diese Meldung nicht sehen wollen. Konkret wird diese\n" -"Warnung mit 'git config set remote.%s.followRemoteHEAD %s' deaktiviert\n" -"bis die Gegenstelle HEAD in etwas anderes ändert." +"anderen Wert wenn Sie diese Meldung nicht sehen wollen. Speziell der Befehl\n" +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"wird die Warnung deaktivieren, bis das Remote-Repository HEAD in etwas\n" +"anderes ändert." msgid "multiple branches detected, incompatible with --set-upstream" msgstr "mehrere Branches erkannt, inkompatibel mit --set-upstream" @@ -6842,6 +6854,9 @@ msgstr "" msgid "repack all other packs except the largest pack" msgstr "alle anderen Pakete, außer das größte Paket, neu packen" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "pack-Präfix zum Speichern eines Pakets mit gelöschten Objekten" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "Fehler beim Parsen des Wertes '%s' von gc.logExpiry" @@ -7659,6 +7674,10 @@ msgid "Cannot come back to cwd" msgstr "Kann nicht zurück zum Arbeitsverzeichnis wechseln" #, c-format +msgid "bad --pack_header: %s" +msgstr "ungültiger --pack_header: %s" + +#, c-format msgid "bad %s" msgstr "%s ist ungültig" @@ -8537,11 +8556,6 @@ msgstr "unbekannte Strategie-Option: -X%s" msgid "malformed input line: '%s'." msgstr "Fehlerhafte Eingabezeile: '%s'." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "" -"Merge kann nicht fortgesetzt werden; unsauberes Ergebnis von %d erhalten" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<Optionen>] [<Commit>...]" @@ -9382,6 +9396,13 @@ msgstr "" "<Objektliste>]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "ungültige Option für --name-hash-version: %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "derzeit erfordert --write-bitmap-index --name-hash-version=1" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -9718,6 +9739,11 @@ msgstr "" "jegliche konfigurierte uploadpack.blobpackfileuri für dieses Protkoll " "ausschließen" +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"die angegebene Name-Hash-Funktion verwenden, um ähnliche Objekte zu " +"gruppieren" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "Tiefe für Verkettung von Unterschieden %d ist zu tief, erzwinge %d" @@ -11006,8 +11032,8 @@ msgstr "Kein Reflog zum Löschen angegeben." msgid "invalid ref format: %s" msgstr "Ungültiges Format für Referenzen: %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<Format> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<Format> [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -11018,6 +11044,9 @@ msgstr "das Referenzformat angeben, in das konvertiert werden soll" msgid "perform a non-destructive dry-run" msgstr "einen zerstörungsfreien Trockenlauf durchführen" +msgid "drop reflogs entirely during the migration" +msgstr "Reflogs während der Migration vollständig zu löschen" + msgid "missing --ref-format=<format>" msgstr "fehlendes --ref-format=<Format>" @@ -11488,8 +11517,14 @@ msgstr "Werde keine URLs entfernen, die nicht für \"push\" bestimmt sind" msgid "be verbose; must be placed before a subcommand" msgstr "erweiterte Ausgaben; muss vor einem Unterbefehl angegeben werden" -msgid "git repack [<options>]" -msgstr "git repack [<Optionen>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<Paketname>]\n" +"[--write-midx] [--name-hash-version=<n>]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11568,6 +11603,12 @@ msgstr "--no-reuse-delta an git-pack-objects übergeben" msgid "pass --no-reuse-object to git-pack-objects" msgstr "--no-reuse-object an git-pack-objects übergeben" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"die Version des Hash-Namens angeben, die für die Gruppierung ähnlicher " +"Objekte nach Pfad verwendet werden soll" + msgid "do not run git-update-server-info" msgstr "git-update-server-info nicht ausführen" @@ -11619,9 +11660,6 @@ msgstr "eine geometrische Progression mit Faktor <N> finden" msgid "write a multi-pack index of the resulting packs" msgstr "ein Multi-Pack-Index des resultierenden Pakets schreiben" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "pack-Präfix zum Speichern eines Pakets mit gelöschten Objekten" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "Paketpräfix, um ein Paket mit herausgefilterten Objekten zu speichern" @@ -11839,9 +11877,6 @@ msgstr "Mit -l kann nur ein Muster angegeben werden" msgid "need some commits to replay" msgstr "zum erneuten Abspielen werden Commits benötigt" -msgid "--onto and --advance are incompatible" -msgstr "--onto und --advance sind inkompatibel" - msgid "all positive revisions given must be references" msgstr "alle angegebenen positiven Commits müssen Referenzen sein" @@ -14571,6 +14606,9 @@ msgstr "ein GNU Arch Repository in Git importieren" msgid "Create an archive of files from a named tree" msgstr "Dateiarchiv von angegebenem Verzeichnis erstellen" +msgid "Download missing objects in a partial clone" +msgstr "fehlender Objekte in einem partiellen Klon herunterladen" + msgid "Use binary search to find the commit that introduced a bug" msgstr "" "Binärsuche verwenden, um den Commit zu finden, der einen Fehler verursacht " @@ -16543,6 +16581,12 @@ msgstr "ungültiges Argument für %s" msgid "invalid regex given to -I: '%s'" msgstr "ungültiger regulärer Ausdruck für -I gegeben: '%s'" +msgid "-G requires a non-empty argument" +msgstr "-G erfordert ein nicht leeres Argument" + +msgid "-S requires a non-empty argument" +msgstr "-S erfordert ein nicht leeres Argument" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "Fehler beim Parsen des --submodule Optionsparameters: '%s'" @@ -18782,6 +18826,10 @@ msgid "unable to write file %s" msgstr "Konnte Datei %s nicht schreiben." #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "konnte nicht in eine wiederholt verschwindende Datei %s schreiben" + +#, c-format msgid "unable to set permission to '%s'" msgstr "Konnte Zugriffsberechtigung auf '%s' nicht setzen." @@ -19355,6 +19403,52 @@ msgstr "Unbekannter Schalter `%c'" msgid "unknown non-ascii option in string: `%s'" msgstr "Unbekannte nicht-Ascii Option in String: `%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " <%s>" + msgid "..." msgstr "..." @@ -19442,6 +19536,21 @@ msgid "failed to parse %s" msgstr "Fehler beim Parsen von %s." #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "Fehlen beim Durchlaufen der Kinder von Baum %s: nicht gefunden" + +#, c-format +msgid "failed to find object %s" +msgstr "Objekt nicht gefunden: %s" + +#, c-format +msgid "failed to find tag %s" +msgstr "Tag nicht gefunden: %s" + +msgid "failed to setup revision walk" +msgstr "Einrichtung des Revisionsgangs fehlgeschlagen" + +#, c-format msgid "Could not make %s writable by group" msgstr "Konnte Gruppenschreibrecht für %s nicht setzen." @@ -19591,6 +19700,25 @@ msgstr "Promisor-Remote-Name kann nicht mit '/' beginnen: %s" msgid "could not fetch %s from promisor remote" msgstr "konnte %s nicht von Promisor-Remote abrufen" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "" +"bekanntes Remote-Repository mit dem Namen '%s', aber mit der URL '%s' statt " +"'%s'" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "unbekannter '%s'-Wert für '%s'-Konfigurationsoption" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "unbekanntes Element '%s' aus Information aus Remote-Repository" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "" +"akzeptiertes partiell geklontes \"Remote-Repository '%s' nicht gefunden" + msgid "object-info: expected flush after arguments" msgstr "object-info: erwartete Flush nach Argumenten" @@ -20428,6 +20556,14 @@ msgid "invalid refspec '%s'" msgstr "ungültige Refspec '%s'" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "Muster '%s' hat keinen '*'" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "Ersetzung '%s' hat keinen '*'" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "Ungültiges Quoting beim \"push-option\"-Wert: '%s'" @@ -20550,6 +20686,28 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: Unbekannter Befehl '%s' von Git" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"Lese von Remote-Repository \"%s/%s\", das zum Entfernen vorgeschlagen wird.\n" +"\n" +"Wenn Sie noch das Verzeichnis \"remotes/\" verwenden, wird empfohlen\n" +"auf konfigurationsbasierte Remote-Repositories umzusteigen:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"Wenn dies nicht möglich ist, teilen Sie uns bitte mit, warum Sie das noch\n" +"verwenden müssen, indem Sie eine E-Mail an <git@vger.kernel.org> senden." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "" "Kürzel für Remote-Repository in der Konfiguration kann nicht mit '/' " @@ -20586,14 +20744,6 @@ msgid "%s tracks both %s and %s" msgstr "%s folgt sowohl %s als auch %s" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "Schlüssel '%s' des Musters hatte kein '*'." - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "Wert '%s' des Musters hat kein '*'." - -#, c-format msgid "src refspec %s does not match any" msgstr "Src-Refspec %s entspricht keiner Referenz." @@ -22519,6 +22669,27 @@ msgstr "" "Anzahl der Einträge im Cache-Verzeichnis, die ungültig gemacht werden sollen " "(Standardwert 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <Optionen> -- <Commit-Optionen>" + +msgid "toggle inclusion of blob objects" +msgstr "Einbeziehung von Blob-Objekten umschalten" + +msgid "toggle inclusion of commit objects" +msgstr "Einbeziehung von Commit-Objekten umschalten" + +msgid "toggle inclusion of tag objects" +msgstr "Einbeziehung von Tag-Objekten umschalten" + +msgid "toggle inclusion of tree objects" +msgstr "Einbeziehung von Tree-Objekten umschalten" + +msgid "toggle pruning of uninteresting paths" +msgstr "Auslassen von uninteressanten Pfaden umschalten" + +msgid "read a pattern list over stdin" +msgstr "Liste von Mustern von der Standard-Eingabe lesen" + #, c-format msgid "commit %s is not marked reachable" msgstr "Commit %s ist nicht als erreichbar gekennzeichnet." @@ -23168,6 +23339,10 @@ msgstr "Fehler: " msgid "warning: " msgstr "Warnung: " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() ist fehlgeschlagen mit Fehler '%s' (%d)\n" + msgid "Fetching objects" msgstr "Anfordern der Objekte" @@ -24190,7 +24365,3 @@ msgstr "Lasse %s mit Backup-Suffix '%s' aus.\n" #, perl-format msgid "Do you really want to send %s? [y|N]: " msgstr "Wollen Sie %s wirklich versenden? [y|N]: " - -#, c-format -#~ msgid "preferred pack (%s) is invalid" -#~ msgstr "bevorzugtes Paket (%s) ist ungültig" @@ -87,8 +87,8 @@ msgid "" msgstr "" "Project-Id-Version: git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-23 18:57+0000\n" -"PO-Revision-Date: 2024-12-29 18:26+0100\n" +"POT-Creation-Date: 2025-03-05 22:57+0000\n" +"PO-Revision-Date: 2025-03-06 16:46+0100\n" "Last-Translator: Cédric Malard <c.malard-git@valdun.net>\n" "Language-Team: Jean-Noël Avila <jn.avila@free.fr>\n" "Language: fr\n" @@ -2452,6 +2452,18 @@ msgstr "git archive : erreur de protocole" msgid "git archive: expected a flush" msgstr "git archive : vidage attendu" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "problème lors du chargement de l'extraction clairsemée" + +msgid "Minimum number of objects to request at a time" +msgstr "Nombre minimum d'objets à demander à chaque fois" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Restreindre les objets manquants à l'extraction clairsemée actuelle" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -3217,10 +3229,6 @@ msgstr "" msgid "git version:\n" msgstr "version git ::\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "échec de uname() avec l'erreur '%s' (%d)\n" - msgid "compiler info: " msgstr "info compilateur : " @@ -4243,8 +4251,93 @@ msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "" "clean.requireForce positionné est true et -f non fourni ; refus de nettoyer" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<options>] [--] <dépôt> [<répertoire>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info : impossible d'ajouter une alternative pour '%s' : %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "échec du stat de '%s'" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s existe et n'est pas un répertoire" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "'%s' est un lien symbolique, refus de cloner avec --local" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "échec du démarrage un itérateur sur '%s'" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "le lien symbolique '%s' existe, refus de cloner avec --local" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "échec pour délier '%s'" + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "le lien dur ne peut pas être vérifié à '%s'" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "le lien dur est différent de la source à '%s'" + +#, c-format +msgid "failed to create link '%s'" +msgstr "échec de la création du lien '%s'" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "échec de la copie vers '%s'" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "échec de l'itération sur '%s'" + +#, c-format +msgid "done.\n" +msgstr "fait.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Le clone a réussi, mais l'extraction a échoué.\n" +"Vous pouvez inspecter ce qui a été extrait avec 'git status'\n" +"et réessayer avec 'git restore --source=HEAD :/'\n" + +msgid "remote did not send all necessary objects" +msgstr "le serveur distant n'a pas envoyé tous les objets nécessaires" + +#, c-format +msgid "unable to update %s" +msgstr "impossible de mettre à jour %s" + +msgid "failed to initialize sparse-checkout" +msgstr "échec lors de l'initialisation l'extraction clairsemée" + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "" +"la HEAD distante réfère à une référence non existante, impossible de " +"l'extraire" + +msgid "unable to checkout working tree" +msgstr "impossible d'extraire la copie de travail" + +msgid "unable to write parameters to config file" +msgstr "impossible d'écrire les paramètres dans le fichier de configuration" + +msgid "cannot repack to clean up" +msgstr "impossible de remballer pour nettoyer" + +msgid "cannot unlink temporary alternates file" +msgstr "impossible de délier le fichier temporaire alternates" msgid "don't clone shallow repository" msgstr "ne pas cloner un dépôt superficiel" @@ -4297,6 +4390,9 @@ msgstr "utiliser <nom> au lieu de 'origin' pour suivre la branche amont" msgid "checkout <branch> instead of the remote's HEAD" msgstr "extraire <branche> au lieu de la HEAD du répertoire distant" +msgid "clone single revision <rev> and check out" +msgstr "cloner la révision unique <rév> et l'extraire" + msgid "path to git-upload-pack on the remote" msgstr "chemin vers git-upload-pack sur le serveur distant" @@ -4318,10 +4414,9 @@ msgstr "approfondit l'historique d'un clone superficiel en excluant une ref" msgid "clone only one branch, HEAD or --branch" msgstr "cloner seulement une branche, HEAD ou --branch" -msgid "don't clone any tags, and make later fetches not to follow them" +msgid "clone tags, and make later fetches not to follow them" msgstr "" -"ne pas cloner les tags et indiquer aux récupérations futures de ne pas le " -"faire" +"cloner les tags et indiquer aux récupérations futures de ne pas le faire" msgid "any cloned submodules will be shallow" msgstr "tous les sous-modules clonés seront superficiels" @@ -4367,97 +4462,8 @@ msgstr "" "un URI pour télécharger des paquets avant de récupérer depuis le distant " "d'origine" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info : impossible d'ajouter une alternative pour '%s' : %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "échec du stat de '%s'" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s existe et n'est pas un répertoire" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "'%s' est un lien symbolique, refus de cloner avec --local" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "échec du démarrage un itérateur sur '%s'" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "le lien symbolique '%s' existe, refus de cloner avec --local" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "échec pour délier '%s'" - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "le lien dur ne peut pas être vérifié à '%s'" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "le lien dur est différent de la source à '%s'" - -#, c-format -msgid "failed to create link '%s'" -msgstr "échec de la création du lien '%s'" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "échec de la copie vers '%s'" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "échec de l'itération sur '%s'" - -#, c-format -msgid "done.\n" -msgstr "fait.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Le clone a réussi, mais l'extraction a échoué.\n" -"Vous pouvez inspecter ce qui a été extrait avec 'git status'\n" -"et réessayer avec 'git restore --source=HEAD :/'\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Impossible de trouver la branche distante '%s' à cloner." - -msgid "remote did not send all necessary objects" -msgstr "le serveur distant n'a pas envoyé tous les objets nécessaires" - -#, c-format -msgid "unable to update %s" -msgstr "impossible de mettre à jour %s" - -msgid "failed to initialize sparse-checkout" -msgstr "échec lors de l'initialisation l'extraction clairsemée" - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "" -"la HEAD distante réfère à une référence non existante, impossible de " -"l'extraire" - -msgid "unable to checkout working tree" -msgstr "impossible d'extraire la copie de travail" - -msgid "unable to write parameters to config file" -msgstr "impossible d'écrire les paramètres dans le fichier de configuration" - -msgid "cannot repack to clean up" -msgstr "impossible de remballer pour nettoyer" - -msgid "cannot unlink temporary alternates file" -msgstr "impossible de délier le fichier temporaire alternates" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<options>] [--] <dépôt> [<répertoire>]" msgid "Too many arguments." msgstr "Trop d'arguments." @@ -4563,6 +4569,10 @@ msgstr "le transport distant a retourné une erreur" msgid "Remote branch %s not found in upstream %s" msgstr "La branche distante %s n'a pas été trouvée dans le dépôt amont %s" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "La révision distante %s n'a pas été trouvée dans le dépôt amont %s" + msgid "You appear to have cloned an empty repository." msgstr "Vous semblez avoir cloné un dépôt vide." @@ -4737,7 +4747,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree : échec de la lecture" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -4747,14 +4757,14 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" -"reword):]<commit>)]\n" +"reword):]<commit>]\n" " [-F <fichier> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<auteur>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" " [-i | -o] [--pathspec-from-file=<fichier> [--pathspec-file-nul]]\n" -" [(--trailer <symbole>[(=|:)<valeur>])...] [-S[<id-clé>]]\n" +" [(--trailer <jeton>[(=|:)<valeur>])...] [-S[<id-clé>]]\n" " [--] [<spéc-de-chemin>...]" msgid "git status [<options>] [--] [<pathspec>...]" @@ -6168,13 +6178,14 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Lancez 'git remote set-head %s %s' pour suivre la modification, ou\n" "réglez l'option de configuration 'remote.%s.followRemoteHEAD' à une\n" "valeur différente si vous ne souhaitez pas voir ce message. Lancer\n" -"spécifiquement 'git config set remote.%s.followRemoteHEAD %s'\n" +"spécifiquement 'git config set remote.%s.followRemoteHEAD warn-if-not-branch-" +"%s'\n" "va désactiver l'alerte jusqu'à ce que le distant change HEAD." msgid "multiple branches detected, incompatible with --set-upstream" @@ -6860,6 +6871,9 @@ msgstr "" msgid "repack all other packs except the largest pack" msgstr "recompacter tous les autres paquets excepté le plus gros paquet" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "préfixe de paquet pour stocker un paquet contenant les objets élagués" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "impossible d'analyser gc.logExpiry %s" @@ -7674,6 +7688,10 @@ msgid "Cannot come back to cwd" msgstr "Impossible de revenir au répertoire de travail courant" #, c-format +msgid "bad --pack_header: %s" +msgstr "mauvais --pack_header : %s" + +#, c-format msgid "bad %s" msgstr "mauvais %s" @@ -8561,10 +8579,6 @@ msgstr "option de stratégie inconnue : -X%s" msgid "malformed input line: '%s'." msgstr "ligne en entrée malformée : '%s'." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "la fusion ne peut pas continuer ; résultat non propre retourné %d" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<options>] [<commit>...]" @@ -9398,6 +9412,13 @@ msgstr "" "objets>]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "option --name-hash-version invalide : %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "actuellement, --write-bitmap-index nécessite --name-hash-version=1" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -9730,6 +9751,11 @@ msgstr "protocole" msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "exclure tout uploadpack.blobpackfileuri configuré avec ce protocole" +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"utiliser la fonction d'empreinte de nom spécifiée pour grouper les objets " +"similaires" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "la profondeur %d de chaîne de delta est trop grande, forcée à %d" @@ -10992,8 +11018,8 @@ msgstr "pas de journal de références à supprimer spécifié" msgid "invalid ref format: %s" msgstr "format de référence invalide : %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<format> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -11004,6 +11030,9 @@ msgstr "spécifier le format de réference vers lequel convertir" msgid "perform a non-destructive dry-run" msgstr "faire l'action en mode simulé non destructif" +msgid "drop reflogs entirely during the migration" +msgstr "abandonner complètement le reflog pendant la migration" + msgid "missing --ref-format=<format>" msgstr "--ref-format=<format> manquant" @@ -11475,8 +11504,14 @@ msgstr "Pas de suppression de toutes les URLs non-push" msgid "be verbose; must be placed before a subcommand" msgstr "être verbeux : doit être placé avant une sous-commande" -msgid "git repack [<options>]" -msgstr "git repack [<options>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<nom-de-paquet>]\n" +"[--write-midx] [--name-hash-version=<n>]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11557,6 +11592,12 @@ msgstr "passer --no-reuse-delta à git-pack-objects" msgid "pass --no-reuse-object to git-pack-objects" msgstr "passer --no-reuse-object à git-pack-objects" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"spécifier la verison d'empreinte de nom à utiliser pour grouper les objets " +"similaires par chemin" + msgid "do not run git-update-server-info" msgstr "ne pas lancer git-update-server-info" @@ -11606,9 +11647,6 @@ msgstr "trouver une progression géométrique avec un facteur <N>" msgid "write a multi-pack index of the resulting packs" msgstr "écrire un index de multi-paquet des paquets résultants" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "préfixe de paquet pour stocker un paquet contenant les objets élagués" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "préfixe de paquet pour stocker un paquet contenant les objets filtrés" @@ -11825,9 +11863,6 @@ msgstr "-l n'accepte qu'un motifs" msgid "need some commits to replay" msgstr "commits requis pour pouvoir rejouer" -msgid "--onto and --advance are incompatible" -msgstr "--onto et --advance sont incompatibles" - msgid "all positive revisions given must be references" msgstr "toutes les révisions positives fournies doivent être des références" @@ -14539,6 +14574,9 @@ msgstr "Importer dans Git un dépôt GNU Arch" msgid "Create an archive of files from a named tree" msgstr "Créer une archive des fichiers depuis un arbre nommé" +msgid "Download missing objects in a partial clone" +msgstr "Télécharger les objets manquants dans un clone partiel" + msgid "Use binary search to find the commit that introduced a bug" msgstr "Trouver par recherche binaire la modification qui a introduit un bogue" @@ -16531,6 +16569,12 @@ msgstr "argument invalide pour %s" msgid "invalid regex given to -I: '%s'" msgstr "regex invalide fournie à -I : '%s'" +msgid "-G requires a non-empty argument" +msgstr "-G exige un argument non vide" + +msgid "-S requires a non-empty argument" +msgstr "-S exige un argument non vide" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "échec de l'analyse du paramètre de l'option --submodule : '%s'" @@ -18767,6 +18811,10 @@ msgid "unable to write file %s" msgstr "impossible d'écrire le fichier %s" #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "impossible d'écrire le fichier %s qui disparaît répétitivement" + +#, c-format msgid "unable to set permission to '%s'" msgstr "impossible de régler les droits de '%s'" @@ -19338,6 +19386,52 @@ msgstr "bascule inconnue « %c »" msgid "unknown non-ascii option in string: `%s'" msgstr "option non-ascii inconnue dans la chaîne : '%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " <%s>" + msgid "..." msgstr "..." @@ -19425,6 +19519,21 @@ msgid "failed to parse %s" msgstr "échec de l'analyse de %s" #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "échec de parcours des enfants de l'arbre %s : non trouvé" + +#, c-format +msgid "failed to find object %s" +msgstr "échec de la recherche de l'objet %s" + +#, c-format +msgid "failed to find tag %s" +msgstr "impossible de trouver l'étiquette %s" + +msgid "failed to setup revision walk" +msgstr "impossible définir un parcours de révisions" + +#, c-format msgid "Could not make %s writable by group" msgstr "Impossible de rendre %s inscriptible pour le groupe" @@ -19581,6 +19690,22 @@ msgstr "un nom de prometteur distant ne peut pas commencer par '/' : %s" msgid "could not fetch %s from promisor remote" msgstr "impossible de récupérer %s depuis le distant de prometteur" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "distant connu nommé '%s' mais avec l'url '%s' au lieu de '%s'" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "valeur inconnue '%s' pour l'option de config '%s'" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "élément inconnu '%s' pour l'info de distant" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "distant accpté de prometteur '%s' non trouvé" + msgid "object-info: expected flush after arguments" msgstr "object-info : vidage attendu après les arguments" @@ -20418,6 +20543,14 @@ msgid "invalid refspec '%s'" msgstr "spécificateur de réference invalide : '%s'" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "la valeur '%s' du motif n'a pas de '*'" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "le remplacement '%s' n'a pas de '*'" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "citation invalide dans la valeur push-option : '%s'" @@ -20539,6 +20672,28 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl : commande inconnue '%s' depuis git" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"lecture depuis \"%s/%s\", dont la suppression est programmée.\n" +"\n" +"Si vous utilisez encore le répertoire \"remotes\", il est recommandé de\n" +"migrer vers une gestion à base de configuration :\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"S'il vous est impossible de migrer, veuillez nous avertir par\n" +"un courriel à <git@vger.kernel.org>." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "" "un raccourci de configuration de distant ne peut pas commencer par '/' : %s" @@ -20574,14 +20729,6 @@ msgid "%s tracks both %s and %s" msgstr "%s suit à la fois %s et %s" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "la clé '%s' du modèle n'a pas de '*'" - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "la valeur '%s' du modèle n'a pas de '*'" - -#, c-format msgid "src refspec %s does not match any" msgstr "" "le spécificateur de référence source %s ne correspond à aucune référence" @@ -22505,6 +22652,27 @@ msgstr "effacer l'arbre de cache avant chaque itération" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "nombre d'entrées dans l'arbre de cache à invalider (par défaut, 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <options> -- <options-de-révision>" + +msgid "toggle inclusion of blob objects" +msgstr "activer l'inclusion des objets blob" + +msgid "toggle inclusion of commit objects" +msgstr "activer l'inclusion des objets commit" + +msgid "toggle inclusion of tag objects" +msgstr "activer l'inclusion des objets étiquette" + +msgid "toggle inclusion of tree objects" +msgstr "activer l'inclusion des objets arbre" + +msgid "toggle pruning of uninteresting paths" +msgstr "activer l'élagage des chemins inintéressants" + +msgid "read a pattern list over stdin" +msgstr "lire les motifs depuis stdin" + #, c-format msgid "commit %s is not marked reachable" msgstr "le commit %s n'est pas marqué joignable" @@ -23151,6 +23319,10 @@ msgstr "erreur : " msgid "warning: " msgstr "avertissement : " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "échec de uname() avec l'erreur '%s' (%d)\n" + msgid "Fetching objects" msgstr "Récupération des objets" @@ -24128,5 +24300,23 @@ msgid "Do you really want to send %s? [y|N]: " msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : " #, c-format +#~ msgid "Could not find remote branch %s to clone." +#~ msgstr "Impossible de trouver la branche distante '%s' à cloner." + +#, c-format +#~ msgid "merging cannot continue; got unclean result of %d" +#~ msgstr "la fusion ne peut pas continuer ; résultat non propre retourné %d" + +#~ msgid "git repack [<options>]" +#~ msgstr "git repack [<options>]" + +#~ msgid "--onto and --advance are incompatible" +#~ msgstr "--onto et --advance sont incompatibles" + +#, c-format +#~ msgid "key '%s' of pattern had no '*'" +#~ msgstr "la clé '%s' du modèle n'a pas de '*'" + +#, c-format #~ msgid "preferred pack (%s) is invalid" #~ msgstr "le paquet préféré (%s) est invalide" @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-23 18:57+0000\n" -"PO-Revision-Date: 2025-01-06 15:50+0700\n" +"POT-Creation-Date: 2025-03-05 22:57+0000\n" +"PO-Revision-Date: 2025-03-09 17:44+0700\n" "Last-Translator: Bagas Sanjaya <bagasdotme@gmail.com>\n" "Language-Team: Indonesian\n" "Language: id\n" @@ -2890,6 +2890,22 @@ msgstr "git archive: kesalahan protokol" msgid "git archive: expected a flush" msgstr "git archive: sebuah bilasan diharapkan" +#: builtin/backfill.c +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +#: builtin/backfill.c +msgid "problem loading sparse-checkout" +msgstr "galat memuat sparse-checkout" + +#: builtin/backfill.c +msgid "Minimum number of objects to request at a time" +msgstr "Jumlah objek minum yang diminta pada suatu waktu" + +#: builtin/backfill.c +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Batasi objek yang hilang ke sparse-checkout saat ini" + #: builtin/bisect.c msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" @@ -3312,7 +3328,7 @@ msgstr "perlihatkan email pengarang daripada nama (asali: off)" msgid "ignore whitespace differences" msgstr "abaikan perbedaan spasi putih" -#: builtin/blame.c builtin/log.c +#: builtin/blame.c builtin/clone.c builtin/log.c msgid "rev" msgstr "revisi" @@ -3829,11 +3845,6 @@ msgid "git version:\n" msgstr "versi git:\n" #: builtin/bugreport.c -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() gagal dengan kesalahan '%s' (%d)\n" - -#: builtin/bugreport.c msgid "compiler info: " msgstr "info pengompilasi: " @@ -5090,8 +5101,112 @@ msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "clean.requireForce 'true' dan -f tidak diberikan: menolak membersihkan" #: builtin/clone.c -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<opsi>] [--] <repo> [<direktori>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: Tidak dapat menambahkan alternatif untuk '%s': %s\n" + +#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c +#, c-format +msgid "failed to stat '%s'" +msgstr "gagal men-stat '%s'" + +#: builtin/clone.c +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s ada dan bukan direktori" + +#: builtin/clone.c +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "'%s' tautan simbolik, menolak mengkloning dengan --local" + +#: builtin/clone.c +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "gagal memulai iterator pada '%s'" + +#: builtin/clone.c +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "tautan simbolik '%s' ada, menolak mengkloning dengan --local" + +#: builtin/clone.c compat/precompose_utf8.c +#, c-format +msgid "failed to unlink '%s'" +msgstr "gagal menghapus tautan '%s'" + +#: builtin/clone.c +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "tautan keras tidak dapat diperiksa pada '%s'" + +#: builtin/clone.c +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "tautan keras berbeda dari sumber pada '%s'" + +#: builtin/clone.c +#, c-format +msgid "failed to create link '%s'" +msgstr "gagal membuat tautan '%s'" + +#: builtin/clone.c +#, c-format +msgid "failed to copy file to '%s'" +msgstr "gagal menyalin berkas ke '%s'" + +#: builtin/clone.c refs/files-backend.c +#, c-format +msgid "failed to iterate over '%s'" +msgstr "gagal iterasi pada '%s'" + +#: builtin/clone.c +#, c-format +msgid "done.\n" +msgstr "selesai.\n" + +#: builtin/clone.c +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Klon sukses, tapi checkout gagal.\n" +"Anda dapat periksa apa yang dicheckout dengan 'git status'\n" +"dan coba lagi dengan 'git restore --source=HEAD :/'\n" + +#: builtin/clone.c fetch-pack.c +msgid "remote did not send all necessary objects" +msgstr "remote tidak mengirim semua objek yang dibutuhkan" + +#: builtin/clone.c +#, c-format +msgid "unable to update %s" +msgstr "tidak dapat memperbarui %s" + +#: builtin/clone.c +msgid "failed to initialize sparse-checkout" +msgstr "gagal menginisalisasi checkout tipis" + +#: builtin/clone.c +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "HEAD remote merujuk pada ref yang tidak ada, tidak dapat men-checkout" + +#: builtin/clone.c +msgid "unable to checkout working tree" +msgstr "tidak dapat men-checkout pohon kerja" + +#: builtin/clone.c +msgid "unable to write parameters to config file" +msgstr "tidak dapat menulis parameter ke berkas konfigurasi" + +#: builtin/clone.c +msgid "cannot repack to clean up" +msgstr "tidak dapat memaket ulang untuk pembersihan" + +#: builtin/clone.c +msgid "cannot unlink temporary alternates file" +msgstr "tidak dapat batal-taut berkas alternatif sementara" #: builtin/clone.c msgid "don't clone shallow repository" @@ -5164,6 +5279,10 @@ msgid "checkout <branch> instead of the remote's HEAD" msgstr "checkout <cabang> daripada HEAD remote" #: builtin/clone.c +msgid "clone single revision <rev> and check out" +msgstr "klon satu revisi <revisi> dan check out" + +#: builtin/clone.c msgid "path to git-upload-pack on the remote" msgstr "jalur ke git-upload-pack pada remote" @@ -5192,8 +5311,8 @@ msgid "clone only one branch, HEAD or --branch" msgstr "klon hanya satu cabang, HEAD atau --branch" #: builtin/clone.c -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "jangan klon tag apapun, dan buat pengambilan nanti tidak mengikutinya" +msgid "clone tags, and make later fetches not to follow them" +msgstr "klon tag dan jangan ikuti mereka pada pengambilan berikutnya" #: builtin/clone.c msgid "any cloned submodules will be shallow" @@ -5251,117 +5370,8 @@ msgid "a URI for downloading bundles before fetching from origin remote" msgstr "sebuah URI untuk mengunduh bundel sebelum mengambil dari remote asal" #: builtin/clone.c -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info: Tidak dapat menambahkan alternatif untuk '%s': %s\n" - -#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c -#, c-format -msgid "failed to stat '%s'" -msgstr "gagal men-stat '%s'" - -#: builtin/clone.c -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s ada dan bukan direktori" - -#: builtin/clone.c -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "'%s' tautan simbolik, menolak mengkloning dengan --local" - -#: builtin/clone.c -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "gagal memulai iterator pada '%s'" - -#: builtin/clone.c -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "tautan simbolik '%s' ada, menolak mengkloning dengan --local" - -#: builtin/clone.c compat/precompose_utf8.c -#, c-format -msgid "failed to unlink '%s'" -msgstr "gagal menghapus tautan '%s'" - -#: builtin/clone.c -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "tautan keras tidak dapat diperiksa pada '%s'" - -#: builtin/clone.c -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "tautan keras berbeda dari sumber pada '%s'" - -#: builtin/clone.c -#, c-format -msgid "failed to create link '%s'" -msgstr "gagal membuat tautan '%s'" - -#: builtin/clone.c -#, c-format -msgid "failed to copy file to '%s'" -msgstr "gagal menyalin berkas ke '%s'" - -#: builtin/clone.c refs/files-backend.c -#, c-format -msgid "failed to iterate over '%s'" -msgstr "gagal iterasi pada '%s'" - -#: builtin/clone.c -#, c-format -msgid "done.\n" -msgstr "selesai.\n" - -#: builtin/clone.c -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Klon sukses, tapi checkout gagal.\n" -"Anda dapat periksa apa yang dicheckout dengan 'git status'\n" -"dan coba lagi dengan 'git restore --source=HEAD :/'\n" - -#: builtin/clone.c -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Tidak dapat menemukan cabang remote %s untuk diklon." - -#: builtin/clone.c fetch-pack.c -msgid "remote did not send all necessary objects" -msgstr "remote tidak mengirim semua objek yang dibutuhkan" - -#: builtin/clone.c -#, c-format -msgid "unable to update %s" -msgstr "tidak dapat memperbarui %s" - -#: builtin/clone.c -msgid "failed to initialize sparse-checkout" -msgstr "gagal menginisalisasi checkout tipis" - -#: builtin/clone.c -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "HEAD remote merujuk pada ref yang tidak ada, tidak dapat men-checkout" - -#: builtin/clone.c -msgid "unable to checkout working tree" -msgstr "tidak dapat men-checkout pohon kerja" - -#: builtin/clone.c -msgid "unable to write parameters to config file" -msgstr "tidak dapat menulis parameter ke berkas konfigurasi" - -#: builtin/clone.c -msgid "cannot repack to clean up" -msgstr "tidak dapat memaket ulang untuk pembersihan" - -#: builtin/clone.c -msgid "cannot unlink temporary alternates file" -msgstr "tidak dapat batal-taut berkas alternatif sementara" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<opsi>] [--] <repo> [<direktori>]" #: builtin/clone.c msgid "Too many arguments." @@ -5492,6 +5502,11 @@ msgid "Remote branch %s not found in upstream %s" msgstr "Cabang remote %s tidak ditemukan di hulu %s" #: builtin/clone.c +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Revisi remote %s tidak ditemukan di hulu %s" + +#: builtin/clone.c msgid "You appear to have cloned an empty repository." msgstr "Anda tampaknya mengklon repositori kosong." @@ -5555,7 +5570,8 @@ msgstr "" "[no-]progress]\n" " <opsi pemisahan>" -#: builtin/commit-graph.c builtin/fetch.c builtin/log.c builtin/repack.c +#: builtin/commit-graph.c builtin/fetch.c builtin/gc.c builtin/log.c +#: builtin/repack.c msgid "dir" msgstr "direktori" @@ -5715,7 +5731,7 @@ msgstr "git commit-tree: gagal membaca" #: builtin/commit.c msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -5725,7 +5741,7 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <komit> | --fixup [(amend|" "reword):]<komit>]\n" " [-F <berkas> | -m <pesan>] [--reset-author] [--allow-empty]\n" @@ -7472,14 +7488,14 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Jalankan 'git remote set-head %s %s' untuk mengikuti perubahan, atau setel\n" "opsi konfigurasi 'remote.%s.followRemoteHEAD' ke nilai yang berbeda jika\n" -"Anda tidak ingin melihat pesan ini lagi. Secara rinci menjalakan\n" -"'git config set remote.%s followRemoteHEAD %s' akan mematikan peringatan\n" -"ini sampai remote mengubah HEAD ke yang lain." +"Anda tidak ingin melihat pesan ini lagi. Secara rinci menjalankan\n" +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s' akan\n" +"mematikan peringatan ini sampai remote mengubah HEAD ke yang lain." #: builtin/fetch.c msgid "multiple branches detected, incompatible with --set-upstream" @@ -8341,6 +8357,10 @@ msgstr "paksa jalankan gc bahkan jika mungkin ada gc lain yang berjalan" msgid "repack all other packs except the largest pack" msgstr "pak ulang semua pak yang lain kecuali pak terbesar" +#: builtin/gc.c builtin/repack.c +msgid "pack prefix to store a pack containing pruned objects" +msgstr "awalan pak untuk menyimpan pak berisi objek terpangkas" + #: builtin/gc.c #, c-format msgid "failed to parse gc.logExpiry value %s" @@ -9353,6 +9373,11 @@ msgstr "tidak dapat menyelesaikan pack-objects untuk mempak ulang tautan lokal" msgid "Cannot come back to cwd" msgstr "tidak dapat kembali ke direktori kerja saat ini" +#: builtin/index-pack.c builtin/unpack-objects.c +#, c-format +msgid "bad --pack_header: %s" +msgstr "--pack_header jelek: %s" + #: builtin/index-pack.c #, c-format msgid "bad %s" @@ -10476,11 +10501,6 @@ msgstr "opsi strategi tidak dikenal: -X%s" msgid "malformed input line: '%s'." msgstr "baris masukan jelek: '%s'." -#: builtin/merge-tree.c -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "penggabungan tidak dapat berlanjut; dapat hasil kotor dari %d" - #: builtin/merge.c msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<opsi>] [<komit>...]" @@ -11524,6 +11544,15 @@ msgstr "" #: builtin/pack-objects.c #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "opsi --name-hash-version tidak valid: %d" + +#: builtin/pack-objects.c +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "saat ini, --write-bitmap-index memerlukan --name-hash-version=1" + +#: builtin/pack-objects.c +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -11935,6 +11964,12 @@ msgstr "" "protokol ini" #: builtin/pack-objects.c +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"gunakan fungsi nama-hash yang dirincikan untuk mengelompokan objek yang " +"serupa" + +#: builtin/pack-objects.c #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "kedalaman rantai delta %d terlalu dalam, memaksakan %d" @@ -13428,8 +13463,8 @@ msgid "invalid ref format: %s" msgstr "format referensi tidak valid: %s" #: builtin/refs.c -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<format> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" #: builtin/refs.c msgid "git refs verify [--strict] [--verbose]" @@ -13444,6 +13479,10 @@ msgid "perform a non-destructive dry-run" msgstr "lakukan uji coba non desktruktif" #: builtin/refs.c +msgid "drop reflogs entirely during the migration" +msgstr "buang keseluruhan log referensi selama migrasi" + +#: builtin/refs.c msgid "missing --ref-format=<format>" msgstr "--ref-format=<format> hilang" @@ -14024,8 +14063,14 @@ msgid "be verbose; must be placed before a subcommand" msgstr "jadi lebih bertele-tele; harus ditempatkan sebelum subperintah" #: builtin/repack.c -msgid "git repack [<options>]" -msgstr "git repack [<opsi>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<nama pak>]\n" +"[--write-midx] [--name-hash-version=<n>]" #: builtin/repack.c msgid "" @@ -14119,6 +14164,13 @@ msgid "pass --no-reuse-object to git-pack-objects" msgstr "lewatkan --no-reuse-object ke git-pack-objects" #: builtin/repack.c +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"tentukan versi nama hash yang digunakan untuk mengelompokan objek yang " +"serupa berdasarkan jalur" + +#: builtin/repack.c msgid "do not run git-update-server-info" msgstr "jangan jalankan git-update-server-info" @@ -14185,10 +14237,6 @@ msgid "write a multi-pack index of the resulting packs" msgstr "tulis indeks multipak dari pak yang dihasilkan" #: builtin/repack.c -msgid "pack prefix to store a pack containing pruned objects" -msgstr "awalan pak untuk menyimpan pak berisi objek terpangkas" - -#: builtin/repack.c msgid "pack prefix to store a pack containing filtered out objects" msgstr "awalan pak untuk menyimpan pak berisi objek tersaring" @@ -14463,10 +14511,6 @@ msgid "need some commits to replay" msgstr "butuh beberapa komit untuk dimainkan ulang" #: builtin/replay.c -msgid "--onto and --advance are incompatible" -msgstr "--onto dan --advance tidak kompatibel" - -#: builtin/replay.c msgid "all positive revisions given must be references" msgstr "semua revisi positif yang diberikan haruslah referensi" @@ -17768,6 +17812,10 @@ msgid "Create an archive of files from a named tree" msgstr "Buat arsip berkas dari pohon bernama" #: command-list.h +msgid "Download missing objects in a partial clone" +msgstr "Unduh objek yang hilang dalam klon parsial" + +#: command-list.h msgid "Use binary search to find the commit that introduced a bug" msgstr "Gunakan pencarian biner untuk mencari komit yang memasukkan bug" @@ -20191,6 +20239,14 @@ msgid "invalid regex given to -I: '%s'" msgstr "regex tidak valid diberikan ke -I: '%s'" #: diff.c +msgid "-G requires a non-empty argument" +msgstr "-G butuh sebuah argumen bukan kosong" + +#: diff.c +msgid "-S requires a non-empty argument" +msgstr "-S butuh sebuah argumen bukan kosong" + +#: diff.c #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "gagal menguraikan parameter opsi --submodule: '%s'" @@ -22888,6 +22944,11 @@ msgstr "tidak dapat menulis berkas %s" #: object-file.c #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "tidak dapat menulis berkas yang menghilang %s terus-menerus" + +#: object-file.c +#, c-format msgid "unable to set permission to '%s'" msgstr "tidak dapat menyetel perizinan ke '%s'" @@ -23579,6 +23640,55 @@ msgstr "sakelar tidak dikenal `%c'" msgid "unknown non-ascii option in string: `%s'" msgstr "opsi non-ascii di dalam untai tidak dikenal: `%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid " <%s>" +msgstr " <%s>" + #: parse-options.c msgid "..." msgstr "..." @@ -23682,6 +23792,25 @@ msgstr "nilai lingkungan boolean '%s' jelek untuk '%s'" msgid "failed to parse %s" msgstr "gagal menguraikan %s" +#: path-walk.c +#, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "gagal berjalan anak pohon %s: tidak ditemukan" + +#: path-walk.c +#, c-format +msgid "failed to find object %s" +msgstr "gagal menemukan objek %s" + +#: path-walk.c +#, c-format +msgid "failed to find tag %s" +msgstr "gagal menemukan tag %s" + +#: path-walk.c +msgid "failed to setup revision walk" +msgstr "gagal men-setup jalan revisi" + #: path.c #, c-format msgid "Could not make %s writable by group" @@ -23868,6 +23997,26 @@ msgstr "nama remote penjanji tidak dapat diawali dengan '/': %s" msgid "could not fetch %s from promisor remote" msgstr "tidak dapat mengambil %s dari remote penjanji" +#: promisor-remote.c +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "remote yang terkenal bernama '%s' tapi dengan url '%s' daripada '%s'" + +#: promisor-remote.c +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "nilai '%s' tidak dikenal untuk opsi konfigurasi '%s'" + +#: promisor-remote.c +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "elemen '%s' dari info remote tidak dikenal" + +#: promisor-remote.c +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "remote penjanji yang diterima '%s' tidak ditemukan" + #: protocol-caps.c msgid "object-info: expected flush after arguments" msgstr "object-info: bilasan diharapkan setelah argumen" @@ -24870,6 +25019,16 @@ msgstr "nama referensi %s simbolik, menyalinnya tidak didukung" msgid "invalid refspec '%s'" msgstr "spek referensi tidak valid '%s'" +#: refspec.c +#, c-format +msgid "pattern '%s' has no '*'" +msgstr "pola '%s' tidak mempunyai '*'" + +#: refspec.c +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "pengganti '%s' tidak mempunyai '*'" + #: remote-curl.c #, c-format msgid "invalid quoting in push-option value: '%s'" @@ -25025,6 +25184,28 @@ msgstr "remote-curl: perintah tidak dikenal '%s' dari git" #: remote.c #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"membaca remote dari \"%s/%s\", yang dinominasikan untuk dihapus.\n" +"\n" +"Jika Anda masih menggunakan direktori \"remotes/\" disarankan untuk\n" +"migrasi ke remote berdasarkan konfigurasi:\n" +"\n" +"\tgit remote rename %s %s\n" +"Jika tidak, mohon beri tahu kami mengapa Anda masih menggunakannya dengan\n" +"mengirimkan surel ke <git@vger.kernel.org>." + +#: remote.c +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "pintasan konfigurasi remote tidak dapat diawali dengan '/': %s" @@ -25068,16 +25249,6 @@ msgstr "%s melacak baik %s dan %s" #: remote.c #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "kunci '%s' dari pola tidak ada '*'" - -#: remote.c -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "nilai '%s' dari pola tidak ada '*'" - -#: remote.c -#, c-format msgid "src refspec %s does not match any" msgstr "spek referensi sumber %s tidak cocok dengan apapun" @@ -27389,6 +27560,34 @@ msgstr "bersihkan pohon tembolok sebelum setiap iterasi" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "jumlah entri di dalam pohon tembolok untuk dinirvalidasi (asali 0)" +#: t/helper/test-path-walk.c +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <opsi> -- <opsi revisi>" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of blob objects" +msgstr "sertakan objek blob" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of commit objects" +msgstr "sertakan objek komit" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tag objects" +msgstr "sertakan objek tag" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tree objects" +msgstr "sertakan objek pohon" + +#: t/helper/test-path-walk.c +msgid "toggle pruning of uninteresting paths" +msgstr "pangkas jalur yang tidak menarik" + +#: t/helper/test-path-walk.c +msgid "read a pattern list over stdin" +msgstr "baca daftar pola dari masukan standar" + #: t/helper/test-reach.c #, c-format msgid "commit %s is not marked reachable" @@ -28148,6 +28347,11 @@ msgstr "kesalahan: " msgid "warning: " msgstr "peringatan: " +#: version.c +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() gagal dengan kesalahan '%s' (%d)\n" + #: walker.c msgid "Fetching objects" msgstr "Mengambil objek" @@ -17602,7 +17602,7 @@ msgstr "Controllo la ridenominazione di '%s' in '%s'\n" #: builtin/mv.c:185 msgid "bad source" -msgstr "sourgente errata" +msgstr "sorgente errata" #: builtin/mv.c:188 msgid "can not move directory into itself" @@ -7,6 +7,7 @@ # Changwoo Ryu <cwryu@debian.org>, 2015-2018. # Sihyeon Jang <uneedsihyeon@gmail.com>, 2018. # Gwan-gyeong Mun <elongbug@gmail.com>, 2018. +# Seoyeon Kwon <syeon0204@gmail.com>, 2025. # # - 작업자는 위 Contributors 목록에 추가해 주세요. # - 번역하면서 80컬럼을 넘어가지 않도록 해 주세요. @@ -7666,7 +7667,7 @@ msgid "" " git commit --allow-empty\n" "\n" msgstr "" -"이전 커맷 빼오기가 비어 있습니다. 아마도 충돌 해결 과정에서 그렇게 됐을\n" +"이전 커밋 빼오기가 비어 있습니다. 아마도 충돌 해결 과정에서 그렇게 됐을\n" "것입니다. 그래도 커밋하려면 다음과 같이 하십시오:\n" "\n" " git commit --allow-empty\n" @@ -1,14 +1,14 @@ # Swedish translations for Git. -# Copyright (C) 2010-2024 Peter Krefting <peter@softwolves.pp.se> +# Copyright (C) 2010-2025 Peter Krefting <peter@softwolves.pp.se> # This file is distributed under the same license as the Git package. -# Peter Krefting <peter@softwolves.pp.se>, 2010-2024. +# Peter Krefting <peter@softwolves.pp.se>, 2010-2025. # msgid "" msgstr "" -"Project-Id-Version: git 2.48.0\n" +"Project-Id-Version: git 2.49.0\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-30 11:57+0100\n" -"PO-Revision-Date: 2024-12-30 12:03+0100\n" +"POT-Creation-Date: 2025-03-10 17:45+0100\n" +"PO-Revision-Date: 2025-03-10 17:48+0100\n" "Last-Translator: Peter Krefting <peter@softwolves.pp.se>\n" "Language-Team: Svenska <tp-sv@listor.tp-sv.se>\n" "Language: sv\n" @@ -1477,7 +1477,7 @@ msgid "" "Use '\\!' for literal leading exclamation." msgstr "" "Negativa mönster ignoreras i git-attribut\n" -"Använd '\\!' för att inleda med ett utropstecken." +"Använd ”\\!” för att inleda med ett utropstecken." #, c-format msgid "cannot fstat gitattributes file '%s'" @@ -2060,7 +2060,7 @@ msgid "" "It does not apply to blobs recorded in its index." msgstr "" "Har du handredigerat din patch?\n" -"Den kan inte tillämpas på blobbar som antecknats i dess index." +"Den kan inte tillämpas på blob:ar som antecknats i dess index." msgid "Falling back to patching base and 3-way merge..." msgstr "" @@ -2316,6 +2316,18 @@ msgstr "git archive: protokollfel" msgid "git archive: expected a flush" msgstr "git archive: förväntade en tömning (flush)" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "problem med att läsa filen sparse-checkout" + +msgid "Minimum number of objects to request at a time" +msgstr "Minsta antal objekt att be om varje gång" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Begränsa saknade objekt till befintlig ”sparse-checkout”" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -2921,7 +2933,7 @@ msgid "delete branch (even if not merged)" msgstr "ta bort gren (även om inte helt sammanslagen)" msgid "move/rename a branch and its reflog" -msgstr "flytta/ta bort en gren och dess reflogg" +msgstr "flytta/ta bort en gren och dess referenslogg" msgid "move/rename a branch, even if target exists" msgstr "flytta/ta bort en gren, även om målet finns" @@ -2930,7 +2942,7 @@ msgid "do not output a newline after empty formatted refs" msgstr "skriv inte ut ett nyradstecken efter tomma formaterade referenser" msgid "copy a branch and its reflog" -msgstr "kopiera en gren och dess reflogg" +msgstr "kopiera en gren och dess referenslogg" msgid "copy a branch, even if target exists" msgstr "kopiera en gren, även om målet finns" @@ -2942,7 +2954,7 @@ msgid "show current branch name" msgstr "visa namn på aktuell gren" msgid "create the branch's reflog" -msgstr "skapa grenens reflogg" +msgstr "skapa grenens referenslogg" msgid "edit the description for the branch" msgstr "redigera beskrivning för grenen" @@ -3055,10 +3067,6 @@ msgstr "" msgid "git version:\n" msgstr "git version:\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() misslyckades med felet ”%s” (%d)\n" - msgid "compiler info: " msgstr "kompilatorinfo:" @@ -3095,7 +3103,7 @@ msgid "" "You can delete any lines you don't wish to share.\n" msgstr "" "Tack för att du skriver en buggraport för Git!\n" -"Om du svarar på följande frågor är det lättare för oss att första " +"Om du svarar på följande frågor är det lättare för oss att förstå " "problemet.\n" "Skriv gärna på engelska\n" "\n" @@ -3332,11 +3340,11 @@ msgid "blob|tree" msgstr "blob|träd" msgid "use a <path> for (--textconv | --filters); Not with 'batch'" -msgstr "använd en <sökväg> för (--textconv | --filters): Inte med 'batch'" +msgstr "använd en <sökväg> för (--textconv | --filters): Inte med ”batch”" #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" -msgstr "'%s=<%s>' behöver '%s' eller '%s'" +msgstr "”%s=<%s>” behöver ”%s” eller ”%s”" msgid "path|tree-ish" msgstr "sökväg|träd-igt" @@ -3368,13 +3376,13 @@ msgid "" "git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] " "<pathname>..." msgstr "" -"git check-attr [--source <träd:igt>] [-a | --all | <attr>...] [--] " +"git check-attr [--source <träd-igt>] [-a | --all | <attr>...] [--] " "<sökväg>..." msgid "" "git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]" msgstr "" -"git check-attr --stdin [-z] [--source <träd:igt>] [-a | --all | <attr>...]" +"git check-attr --stdin [-z] [--source <träd-igt>] [-a | --all | <attr>...]" msgid "report all attributes set on file" msgstr "visa alla attribut som satts på filen" @@ -3887,7 +3895,7 @@ msgid "create/reset and checkout a branch" msgstr "skapa/nollställ och checka ut en gren" msgid "create reflog for new branch" -msgstr "skapa reflogg för ny gren" +msgstr "skapa referenslogg för ny gren" msgid "second guess 'git checkout <no-such-branch>' (default)" msgstr "förutspå ”git checkout <gren-saknas>” (förval)" @@ -4062,8 +4070,91 @@ msgstr "ta endast bort ignorerade filer" msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "clean.requireForce är true och -f angavs inte: vägrar städa" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<flaggor>] [--] <arkiv> [<kat>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: Kan inte skapa suppleant för ”%s”: %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "misslyckades ta status på ”%s”" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s finns och är ingen katalog" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "”%s” är en symbolisk länk, vägrar klona med --local" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "misslyckades starta iterator över ”%s”" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "symbolisk länk ”%s” finns redan, vägrar klona med --local" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "misslyckades ta bort länken ”%s”" + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "hård länk kan inte kontrolleras vid ”%s”" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "hård länk skiljer sig från källan vid ”%s”" + +#, c-format +msgid "failed to create link '%s'" +msgstr "misslyckades skapa länken ”%s”" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "misslyckades kopiera filen till ”%s”" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "misslyckades iterera över ”%s”" + +#, c-format +msgid "done.\n" +msgstr "klart.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Klonen lyckades, men utcheckningen misslyckades.\n" +"Du kan inspektera det som checkades ut med ”git status”\n" +"och försöka med ”git restore --source=HEAD :/”\n" + +msgid "remote did not send all necessary objects" +msgstr "fjärren sände inte alla nödvändiga objekt" + +#, c-format +msgid "unable to update %s" +msgstr "kan inte uppdatera %s" + +msgid "failed to initialize sparse-checkout" +msgstr "misslyckades initiera sparse-checkout" + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "HEAD hos fjärren pekar på en obefintlig referens, kan inte checka ut" + +msgid "unable to checkout working tree" +msgstr "kan inte checka ut arbetskatalogen" + +msgid "unable to write parameters to config file" +msgstr "kan inte skriva parametrar till konfigurationsfilen" + +msgid "cannot repack to clean up" +msgstr "kan inte packa om för att städa upp" + +msgid "cannot unlink temporary alternates file" +msgstr "kunde inte ta bort temporär ”alternates”-fil" msgid "don't clone shallow repository" msgstr "klona inte grunt arkiv" @@ -4116,6 +4207,9 @@ msgstr "använd <namn> istället för ”origin” för att spåra uppströms" msgid "checkout <branch> instead of the remote's HEAD" msgstr "checka ut <gren> istället för fjärrens HEAD" +msgid "clone single revision <rev> and check out" +msgstr "klona ensam revision <rev> och checka ut" + msgid "path to git-upload-pack on the remote" msgstr "sökväg till git-upload-pack på fjärren" @@ -4137,8 +4231,8 @@ msgstr "fördjupa historik för grund klon, exkludera ref" msgid "clone only one branch, HEAD or --branch" msgstr "klona endast en gren, HEAD eller --branch" -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "klona inga taggar och gör att senare hämtningar inte följer dem" +msgid "clone tags, and make later fetches not to follow them" +msgstr "klona taggar och gör att senare hämtningar inte följer dem" msgid "any cloned submodules will be shallow" msgstr "klonade undermoduler kommer vara grunda" @@ -4179,95 +4273,8 @@ msgstr "uri" msgid "a URI for downloading bundles before fetching from origin remote" msgstr "en URI för att hämta buntar innan de hämtas från ursprungsfjärr" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info: Kan inte skapa suppleant för ”%s”: %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "misslyckades ta status på ”%s”" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s finns och är ingen katalog" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "”%s” är en symbolisk länk, vägrar klona med --local" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "misslyckades starta iterator över ”%s”" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "symbolisk länk ”%s” finns redan, vägrar klona med --local" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "misslyckades ta bort länken ”%s”" - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "hård länk kan inte kontrolleras vid ”%s”" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "hård länk skiljer sig från källan vid ”%s”" - -#, c-format -msgid "failed to create link '%s'" -msgstr "misslyckades skapa länken ”%s”" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "misslyckades kopiera filen till ”%s”" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "misslyckades iterera över ”%s”" - -#, c-format -msgid "done.\n" -msgstr "klart.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Klonen lyckades, men utcheckningen misslyckades.\n" -"Du kan inspektera det som checkades ut med ”git status”\n" -"och försöka med ”git restore --source=HEAD :/”\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Kunde inte hitta fjärrgrenen %s för att klona." - -msgid "remote did not send all necessary objects" -msgstr "fjärren sände inte alla nödvändiga objekt" - -#, c-format -msgid "unable to update %s" -msgstr "kan inte uppdatera %s" - -msgid "failed to initialize sparse-checkout" -msgstr "misslyckades initiera sparse-checkout" - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "HEAD hos fjärren pekar på en obefintlig referens, kan inte checka ut" - -msgid "unable to checkout working tree" -msgstr "kan inte checka ut arbetskatalogen" - -msgid "unable to write parameters to config file" -msgstr "kan inte skriva parametrar till konfigurationsfilen" - -msgid "cannot repack to clean up" -msgstr "kan inte packa om för att städa upp" - -msgid "cannot unlink temporary alternates file" -msgstr "kunde inte ta bort temporär ”alternates”-fil" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<flaggor>] [--] <arkiv> [<kat>]" msgid "Too many arguments." msgstr "För många argument." @@ -4367,6 +4374,10 @@ msgstr "fjärrtransport rapporterade fel" msgid "Remote branch %s not found in upstream %s" msgstr "Fjärrgrenen %s hittades inte i uppströmsarkivet %s" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Fjärr-revisionen %s hittades inte i uppströmsarkivet %s" + msgid "You appear to have cloned an empty repository." msgstr "Du verkar ha klonat ett tomt arkiv." @@ -4540,7 +4551,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree: misslyckades läsa" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -4550,7 +4561,7 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<läge>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<läge>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <incheckning> | --fixup [(amend|" "reword):]<incheckning>]\n" " [-F <fil> | -m <medd>] [--reset-author] [--allow-empty]\n" @@ -4791,7 +4802,7 @@ msgstr "Ange meddelandet en av flaggorna -m eller -F.\n" #, c-format msgid "--author '%s' is not 'Name <email>' and matches no existing author" msgstr "" -"--author '%s' är inte 'Namn <epost>' och motsvarar ingen befintlig författare" +"--author ”%s” är inte ”Namn <epost>” och motsvarar ingen befintlig författare" #, c-format msgid "Invalid ignored mode '%s'" @@ -5202,7 +5213,7 @@ msgid "writing to stdin is not supported" msgstr "skriva till standard in stöds inte" msgid "writing config blobs is not supported" -msgstr "skriva konfigurations-blobbar stöds inte" +msgstr "skriva konfigurations-blob:ar stöds inte" #, c-format msgid "" @@ -5239,7 +5250,7 @@ msgid "" "section in \"git help worktree\" for details" msgstr "" "--worktree kan inte användas med flera arbetskataloger om inte\n" -"konfigurationsutöknignen worktreeConfig har aktiverats. Läsa stycket\n" +"konfigurationsutökningen worktreeConfig har aktiverats. Läsa stycket\n" "”KONFIGURATIONSFIL” i ”git help worktree” för detaljer" msgid "Other" @@ -5325,7 +5336,7 @@ msgid "editing stdin is not supported" msgstr "redigering av standard in stöds ej" msgid "editing blobs is not supported" -msgstr "redigering av blobbar stöds ej" +msgstr "redigering av blob:ar stöds ej" #, c-format msgid "cannot create configuration file %s" @@ -5601,7 +5612,7 @@ msgstr "objektet ”%s” som angavs är felaktigt." #, c-format msgid "more than two blobs given: '%s'" -msgstr "mer än två blobbar angavs: ”%s”" +msgstr "mer än två blob:ar angavs: ”%s”" #, c-format msgid "unhandled object '%s' given." @@ -5760,7 +5771,7 @@ msgid "reference parents which are not in fast-export stream by object id" msgstr "referera föräldrar som inte finns i fast-export-ström med objekt-id" msgid "show original object ids of blobs/commits" -msgstr "visa ursprungliga objekt-id för blobbar/incheckningar" +msgstr "visa ursprungliga objekt-id för blob:ar/incheckningar" msgid "label tags with mark ids" msgstr "märk taggar med märke-id" @@ -5931,14 +5942,14 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Kör ”git remote set-head %s %s” för att följa ändringen, eller sätt\n" "konfigurationsflaggan ”remote %s.followRemoteHEAD” till ett annat värde\n" "om du inte vill se det här meddelandet. Du kan specifikt inaktivera\n" "varningen till fjärren ändrar HEAD till något annat genom att köra\n" -"”git config set remote %s.followRemoteHEAD %s”." +"”git config set remote %s.followRemoteHEAD warn-if-not-branch-%s”." msgid "multiple branches detected, incompatible with --set-upstream" msgstr "flera grenar upptäcktes, inkompatibelt med --set-upstream" @@ -6328,11 +6339,11 @@ msgstr "%s: objekt trasigt eller saknas" #, c-format msgid "%s: invalid reflog entry %s" -msgstr "%s: ogiltig reflog-post %s" +msgstr "%s: ogiltig referensloggpost %s" #, c-format msgid "Checking reflog %s->%s" -msgstr "Kontrollerar reflog %s→%s" +msgstr "Kontrollerar referenslogg %s→%s" #, c-format msgid "%s: invalid sha1 pointer %s" @@ -6441,7 +6452,7 @@ msgid "make index objects head nodes" msgstr "gör indexobjekt till huvudnoder" msgid "make reflogs head nodes (default)" -msgstr "gör refloggar till huvudnoder (standard)" +msgstr "gör referensloggar till huvudnoder (standard)" msgid "also consider packs and alternate objects" msgstr "ta även hänsyn till paket och supplerande objekt" @@ -6502,11 +6513,11 @@ msgstr "kunde inte skapa fsmonitor-kaka ”%s”" #, c-format msgid "fsmonitor: cookie_result '%d' != SEEN" -msgstr "fsmonitor: cookie_result '%d' != SEEN" +msgstr "fsmonitor: cookie_result ”%d” != SEEN" #, c-format msgid "could not start IPC thread pool on '%s'" -msgstr "kunde inte starta IPC-trådpol på ”%s”" +msgstr "kunde inte starta IPC-trådpool på ”%s”" msgid "could not start fsmonitor listener thread" msgstr "kunde inte starta fsmonitor-lyssnartråd" @@ -6618,6 +6629,9 @@ msgstr "tvinga gc-körning även om en annan gc kanske körs" msgid "repack all other packs except the largest pack" msgstr "packa om alla paket förutom det största paketet" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "paketprefix att lagra ett paket som innehåller bortrensade objekt" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "misslyckades tolka värdet %s för gc.logExpiry" @@ -7176,7 +7190,7 @@ msgstr "flaggan ”%s” tar inte några argument som inte är flaggor" msgid "" "the '--no-[external-commands|aliases]' options can only be used with '--all'" msgstr "" -"flaggorna '--no-[external-commands|aliases]' kan endast användas med ”--all”" +"flaggorna ”--no-[external-commands|aliases]” kan endast användas med ”--all”" #, c-format msgid "usage: %s%s" @@ -7407,6 +7421,10 @@ msgid "Cannot come back to cwd" msgstr "Kan inte gå tillbaka till arbetskatalogen (cwd)" #, c-format +msgid "bad --pack_header: %s" +msgstr "felaktig --pack_header: %s" + +#, c-format msgid "bad %s" msgstr "felaktig %s" @@ -7977,7 +7995,7 @@ msgid "suppress duplicate entries" msgstr "undertryck dublettposter" msgid "show sparse directories in the presence of a sparse index" -msgstr "visa glesa kataloger när et glest index existerar" +msgstr "visa glesa kataloger när ett glest index existerar" msgid "" "--format cannot be used with -s, -o, -k, -t, --resolve-undo, --deduplicate, " @@ -8261,10 +8279,6 @@ msgstr "okänd strategiflagga: -X%s" msgid "malformed input line: '%s'." msgstr "felaktig indatarad: ”%s”." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "sammanslagning kan inte fortsätta; fick inte rent resultat från %d" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<flaggor>] [<incheckning>...]" @@ -8969,7 +8983,7 @@ msgid "failed to remove 'git notes merge' worktree" msgstr "misslyckades ta bort arbetskatalogen för ”git notes merge”" msgid "failed to read ref NOTES_MERGE_PARTIAL" -msgstr "misslyckades läsa references NOTES_MERGE_PARTIAL" +msgstr "misslyckades läsa referensen NOTES_MERGE_PARTIAL" msgid "could not find commit from NOTES_MERGE_PARTIAL." msgstr "kunde inte hitta incheckning från NOTES_MERGE_PARTIAL." @@ -9081,6 +9095,13 @@ msgstr "" "git pack-objects [<flaggor>] <basnamn> [< <reflista> | < <objektlista>]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "ogiltig flagga för --name-hash-version: %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "--write-bitmap-index kräver för närvarande, --name-hash-version=1" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -9190,14 +9211,14 @@ msgid "" "value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-" "hash> <uri>' (got '%s')" msgstr "" -"värdet på uploadpack.blobpackfileuri måste vara på formen '<objekt-hash> " -"<paket-hash> <uri>' (fick '%s')" +"värdet på uploadpack.blobpackfileuri måste vara på formen ”<objekt-hash> " +"<paket-hash> <uri>” (fick ”%s”)" #, c-format msgid "" "object already configured in another uploadpack.blobpackfileuri (got '%s')" msgstr "" -"objektet redan konfigurerat i et annat uploadpack.blobpackfileuri (fick '%s)" +"objektet redan konfigurerat i ett annat uploadpack.blobpackfileuri (fick ”%s”" #, c-format msgid "could not get type of object %s in pack %s" @@ -9401,6 +9422,10 @@ msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "" "uteslut redan konfigurerade uploadpack.blobpackfileuri med detta protokoll" +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"använd den angivna namn-hash-funktionen för att gruppera liknande objekt" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "deltakedjedjupet %d är för djupt, påtvingar %d" @@ -10189,7 +10214,7 @@ msgstr "" "Ange vilken gren du vill ombasera mot.\n" "Se git-rebase(1) för detaljer.\n" "\n" -" git rebase '<gren>'\n" +" git rebase ”<gren>”\n" "\n" #, c-format @@ -10603,7 +10628,8 @@ msgid "process the reflogs of all references" msgstr "hantera referensloggar för alla referenser" msgid "limits processing to reflogs from the current worktree only" -msgstr "begränsar hantering av referensloggar till endast aktuell arbetskatalog" +msgstr "" +"begränsar hantering av referensloggar till endast aktuell arbetskatalog" #, c-format msgid "Marking reachable objects..." @@ -10620,8 +10646,8 @@ msgstr "ingen referenslogg att ta bort angavs" msgid "invalid ref format: %s" msgstr "felaktigt referensformat: %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<format> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -10632,6 +10658,9 @@ msgstr "ange referensformatet att konvertera till" msgid "perform a non-destructive dry-run" msgstr "utför ett icke-destruktiv testkörning" +msgid "drop reflogs entirely during the migration" +msgstr "kasta referensloggar helt under migreringen" + msgid "missing --ref-format=<format>" msgstr "saknad --ref-format=<format>" @@ -11091,8 +11120,14 @@ msgstr "Kommer inte ta bort alla icke-sänd-URL:er" msgid "be verbose; must be placed before a subcommand" msgstr "var pratsam; måste skrivas före ett underkommando" -msgid "git repack [<options>]" -msgstr "git repack [<flaggor>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<paket-namn>]\n" +"[--write-midx] [--name-hash-version=<n>]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11166,6 +11201,12 @@ msgstr "sänd --no-reuse-delta till git-pack-objects" msgid "pass --no-reuse-object to git-pack-objects" msgstr "sänd --no-reuse-object till git-pack-objects" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"ange den namnhash-version som ska användas för att gruppera liknande objekt " +"efter sökväg" + msgid "do not run git-update-server-info" msgstr "kör inte git-update-server-info" @@ -11214,9 +11255,6 @@ msgstr "hitta ett geometrisk förlopp med faktor <N>" msgid "write a multi-pack index of the resulting packs" msgstr "skriv ett flerpaketsindex för de skapade paketen" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "paketprefix att lagra ett paket som innehåller bortrensade objekt" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "paketprefix att lagra ett paket som innehåller utfiltrerade objekt" @@ -11433,9 +11471,6 @@ msgstr "endast ett mönster kan anges med -l" msgid "need some commits to replay" msgstr "behöver några incheckningar för omspelning" -msgid "--onto and --advance are incompatible" -msgstr "--onto och --advance kan inte kombineras" - msgid "all positive revisions given must be references" msgstr "alla positiva revisioner som anges måste vara referenser" @@ -12020,7 +12055,7 @@ msgid "<n>[,<base>]" msgstr "<n>[,<bas>]" msgid "show <n> most recent ref-log entries starting at base" -msgstr "visa <n> nyaste refloggposter med början på bas" +msgstr "visa <n> nyaste referensloggposter med början på bas" msgid "no branches given, and HEAD is not valid" msgstr "inga grenar angavs, och HEAD är inte giltigt" @@ -12134,7 +12169,7 @@ msgid "" "directory '%s' contains untracked files, but is not in the sparse-checkout " "cone" msgstr "" -"katalogen ”%s” innehåller ospårade filer, men är inte i området som ages i " +"katalogen ”%s” innehåller ospårade filer, men är inte i området som anges i " "”sparse-checkout”" #, c-format @@ -12726,7 +12761,7 @@ msgstr "misslyckades klona ”%s” till undermodulsökvägen ”%s”" #, c-format msgid "could not get submodule directory for '%s'" -msgstr "kunde inte få tag i undermodulkatalog för ”%s”" +msgstr "kunde inte få tag i undermodulskatalog för ”%s”" msgid "alternative anchor for relative paths" msgstr "alternativa ankare för relativa sökvägar" @@ -12830,8 +12865,8 @@ msgid "" "Fetched in submodule path '%s', but it did not contain %s. Direct fetching " "of that commit failed." msgstr "" -"Hämtade i undermodulssökvägen ”%s”, men den innehöll inte %s. Direkt " -"hämtning av incheckningen misslyckades." +"Hämtade i undermodulsökvägen ”%s”, men den innehöll inte %s. Direkt hämtning " +"av incheckningen misslyckades." #, c-format msgid "could not initialize submodule at path '%s'" @@ -13199,7 +13234,7 @@ msgid "replace the tag if exists" msgstr "ersätt taggen om den finns" msgid "create a reflog" -msgstr "skapa en reflog" +msgstr "skapa en referenslogg" msgid "Tag listing options" msgstr "Alternativ för listning av taggar" @@ -13924,7 +13959,7 @@ msgstr "okänd kapabilitet ”%s”" #, c-format msgid "'%s' does not look like a v2 or v3 bundle file" -msgstr "'%s' ser inte ut som en v2- eller v3-bunt-fil" +msgstr "”%s” ser inte ut som en v2- eller v3-bunt-fil" #, c-format msgid "unrecognized header: %s%s (%d)" @@ -14058,6 +14093,9 @@ msgstr "Importera ett GNU Arch-arkiv till Git" msgid "Create an archive of files from a named tree" msgstr "Skapa ett arkiv över filer från ett namngivet träd" +msgid "Download missing objects in a partial clone" +msgstr "Hämta saknade objekt i en delvis kloning" + msgid "Use binary search to find the commit that introduced a bug" msgstr "Använd binärsökning för att hitta ändringen som introducerade ett fel" @@ -14164,7 +14202,7 @@ msgid "Compare a tree to the working tree or index" msgstr "Jämför en träd med arbetskatalogen eller indexet" msgid "Compares the content and mode of blobs found via two tree objects" -msgstr "Visar innehåll och läge för blobbar som hittats via två trädobjekt" +msgstr "Visar innehåll och läge för blob:ar som hittats via två trädobjekt" msgid "Show changes using common diff tools" msgstr "Visa ändringar med vanliga diff-verktyg" @@ -14996,19 +15034,19 @@ msgstr "kunde inte läsa katalogändringar [GLE %ld]" #, c-format msgid "opendir('%s') failed" -msgstr "opendir('%s') misslyckades" +msgstr "opendir(”%s”) misslyckades" #, c-format msgid "lstat('%s') failed" -msgstr "lstat('%s') misslyckades" +msgstr "lstat(”%s”) misslyckades" #, c-format msgid "strbuf_readlink('%s') failed" -msgstr "strbuf_readlink('%s') misslyckades" +msgstr "strbuf_readlink(”%s”) misslyckades" #, c-format msgid "closedir('%s') failed" -msgstr "closedir('%s') misslyckades" +msgstr "closedir(”%s”) misslyckades" #, c-format msgid "[GLE %ld] unable to open for read '%ls'" @@ -15335,7 +15373,7 @@ msgstr "referensen ”%s” pekar inte på en blob" #, c-format msgid "unable to resolve config blob '%s'" -msgstr "kan inte slå upp konfigurerings-blobben ”%s”" +msgstr "kan inte slå upp konfigurerings-blob:en ”%s”" msgid "unable to parse command-line config" msgstr "kan inte tolka kommandoradskonfiguration" @@ -15968,6 +16006,12 @@ msgstr "ogiltigt argument för %s" msgid "invalid regex given to -I: '%s'" msgstr "ogiltigt reguljärt uttryck angavs för -I: ”%s”" +msgid "-G requires a non-empty argument" +msgstr "-G kräver ett icke-tomt argument" + +msgid "-S requires a non-empty argument" +msgstr "-S kräver ett icke-tomt argument" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "misslyckades tolka argument till flaggan --submodule: ”%s”" @@ -16080,7 +16124,7 @@ msgid "" "do not munge pathnames and use NULs as output field terminators in --raw or " "--numstat" msgstr "" -"skriv inte om sökvägsnamn och använd NUL-tecken som fältseparerare i --raw " +"skriv inte om sökvägsnamn och använd NUL-tecken som fältavdelare i --raw " "eller --numstat" msgid "<prefix>" @@ -16495,7 +16539,7 @@ msgid "already have %s (%s)" msgstr "har redan %s (%s)" msgid "fetch-pack: unable to fork off sideband demultiplexer" -msgstr "fetch-patch: kan inte grena (fork) av sidbandsmultiplexare" +msgstr "fetch-patch: kan inte grena (fork) av sidbands-avmultiplexare" msgid "protocol error: bad pack header" msgstr "protokollfel: felaktigt packhuvud" @@ -16689,7 +16733,7 @@ msgstr "" "”git help -a” och ”git help -g” visar tillgängliga underkommandon och\n" "några konceptvägledningar. Se ”git help <kommando>” eller ”git help\n" "<koncept>” för att läsa mer om specifika underkommandon och koncept.\n" -"See ”git help git” för en översikt över systemet." +"Se ”git help git” för en översikt över systemet." #, c-format msgid "unsupported command listing type '%s'" @@ -17020,7 +17064,7 @@ msgstr "inte ett git-arkiv" #, c-format msgid "argument to --packfile must be a valid hash (got '%s')" msgstr "" -"argumentet till --packfile måste vara ett giltigt hashvärde (fick '%s')" +"argumentet till --packfile måste vara ett giltigt hashvärde (fick ”%s”)" #, c-format msgid "negative value for http.postBuffer; defaulting to %d" @@ -17056,7 +17100,7 @@ msgid "" " asked for: %s\n" " redirect: %s" msgstr "" -"kan inte uppdatera urlbas från omdirigerin:\n" +"kan inte uppdatera urlbas från omdirigering:\n" " bad om: %s\n" " omdirigering: %s" @@ -17914,7 +17958,7 @@ msgid "multi-pack-index stores a 64-bit offset, but off_t is too small" msgstr "multi-pack-index innehåller 64-bitars offset, men off_t är för liten" msgid "multi-pack-index large offset out of bounds" -msgstr "stort offset för mult-pack-index utanför gränsen" +msgstr "stort offset för multi-pack-index utanför gränsen" msgid "multi-pack-index file exists, but failed to parse" msgstr "multi-pack-indexfilen finns, men kunde inte tolkas" @@ -17985,7 +18029,7 @@ msgstr "Kan inte checka in oinitierat/orefererat anteckningsträd" #, c-format msgid "Bad notes.rewriteMode value: '%s'" -msgstr "Felaktigt värde för notes.rewriteMode: '%s'" +msgstr "Felaktigt värde för notes.rewriteMode: ”%s”" #, c-format msgid "Refusing to rewrite notes in %s (outside of refs/notes/)" @@ -18135,6 +18179,10 @@ msgid "unable to write file %s" msgstr "kan inte skriva filen %s" #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "kan inte skriva till filen %s som hela tiden försvinner" + +#, c-format msgid "unable to set permission to '%s'" msgstr "kan inte sätta behörigheten till ”%s”" @@ -18538,7 +18586,8 @@ msgstr "bitkarteresultat stämmer inte överens" #, c-format msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" -msgstr "pseudosammanslagningsindex utanför intervallet (%<PRIu32> ≥ %<PRIuMAX>)" +msgstr "" +"pseudosammanslagningsindex utanför intervallet (%<PRIu32> ≥ %<PRIuMAX>)" #, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" @@ -18694,6 +18743,52 @@ msgstr "okänd flagga ”%c”" msgid "unknown non-ascii option in string: `%s'" msgstr "okänd icke-ascii-flagga i strängen: ”%s”" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " <%s>" + msgid "..." msgstr "..." @@ -18779,6 +18874,21 @@ msgid "failed to parse %s" msgstr "misslyckades tolka %s" #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "misslyckades traversera löven i trädet %s: hittades inte" + +#, c-format +msgid "failed to find object %s" +msgstr "misslyckades hitta objektet %s" + +#, c-format +msgid "failed to find tag %s" +msgstr "misslyckades hitta taggen %s" + +msgid "failed to setup revision walk" +msgstr "misslyckades starta revisionstraversering" + +#, c-format msgid "Could not make %s writable by group" msgstr "Kunde inte göra %s skrivbar för gruppen" @@ -18923,6 +19033,22 @@ msgstr "kontraktsfjärr kan inte börja med ”/”: %s" msgid "could not fetch %s from promisor remote" msgstr "kunde inte hämta %s från kontraktsfjärr" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "känd fjärr som heter ”%s” med med url:en ”%s” istället för ”%s”" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "okänt värde ”%s” för inställningen ”%s”" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "okänt värde ”%s” från fjärrinformation" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "godkänd kontraktsfjärr ”%s” hittades inte" + msgid "object-info: expected flush after arguments" msgstr "object-info: förväntade ”flush” efter argument" @@ -19248,7 +19374,7 @@ msgstr "" " enrads, om inget incheckningsmeddelande angavs); använd\n" " -c <incheckning> för att skriva om meddelandet.\n" "u, update-ref <ref> = spåra en platshållare för <ref> att uppdatera\n" -" till denna position bland nya inchecknngar.\n" +" till denna position bland nya incheckningar.\n" " <ref> uppdateras i slutet av ombaseringen.\n" "\n" "Du kan byta ordning på raderna; de utförs uppifrån och ned.\n" @@ -19616,7 +19742,7 @@ msgid "refusing to update ref with bad name '%s'" msgstr "vägrar uppdatera referens med trasigt namn ”%s”" msgid "refusing to force and skip creation of reflog" -msgstr "vägrar att tvinga och hoppa över skapande av reflogg" +msgstr "vägrar att tvinga och hoppa över skapande av referenslogg" #, c-format msgid "update_ref failed for ref '%s': %s" @@ -19749,6 +19875,14 @@ msgid "invalid refspec '%s'" msgstr "felaktig referensspecifikation: ”%s”" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "mönstret ”%s” innehåller ingen ”*”" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "ersättningen ”%s” innehåller ingen ”*”" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "felaktig citering på värde för push-option: ”%s”" @@ -19867,6 +20001,28 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: okänt kommando ”%s” från git" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"läser fjärren från ”%s/%s”, som har nominerats för borttagning.\n" +"\n" +"Om du fortfarande använder ”remotes/”-katalogen rekommenderas du\n" +"migrera till konfigurationsbaserade fjärrar:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"Om du inte kan det, berätta för oss varför du fortfarande behöver\n" +"använda det på e-post till <git@vger.kernel.org>." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "konfigurerad kortform för fjärr kan inte börja med ”/”: %s" @@ -19901,14 +20057,6 @@ msgid "%s tracks both %s and %s" msgstr "%s spårar både %s och %s" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "nyckeln ”%s” i mönstret innehåller ingen ”*”" - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "värdet ”%s” i mönstret innehåller ingen ”*”" - -#, c-format msgid "src refspec %s does not match any" msgstr "käll-referensspecifikationen %s motsvarar ingen" @@ -21798,6 +21946,27 @@ msgstr "töm cacheträdet före varje iteration" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "antal poster i cacheträdet att ogiltigförklara (förval är 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <flaggor> -- <revision-flaggor>" + +msgid "toggle inclusion of blob objects" +msgstr "växla om blob-objekt ska vara med eller inte" + +msgid "toggle inclusion of commit objects" +msgstr "växla om incheckningsobjekt ska vara med eller inte" + +msgid "toggle inclusion of tag objects" +msgstr "växla om taggobjekt ska vara med eller inte" + +msgid "toggle inclusion of tree objects" +msgstr "växla om trädobjekt ska vara med eller inte" + +msgid "toggle pruning of uninteresting paths" +msgstr "växla bortrensning av ointressanta sökvägar" + +msgid "read a pattern list over stdin" +msgstr "läs en mönsterlista från standard in" + #, c-format msgid "commit %s is not marked reachable" msgstr "incheckning %s är inte märkt nåbar" @@ -22431,6 +22600,10 @@ msgstr "fel: " msgid "warning: " msgstr "varning: " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() misslyckades med felet ”%s” (%d)\n" + msgid "Fetching objects" msgstr "Hämtar objekt" @@ -23265,7 +23438,7 @@ msgstr "Nödvändig SMTP-server har inte angivits korrekt." #, perl-format msgid "Server does not support STARTTLS! %s" -msgstr "Servern stöder inte SMARTTLS! %s" +msgstr "Servern stöder inte STARTTLS! %s" #, perl-format msgid "STARTTLS failed! %s" @@ -96,8 +96,8 @@ msgid "" msgstr "" "Project-Id-Version: Git Turkish Localization Project\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-23 18:57+0000\n" -"PO-Revision-Date: 2025-01-01 15:00+0300\n" +"POT-Creation-Date: 2025-03-11 15:01+0300\n" +"PO-Revision-Date: 2025-03-11 15:00+0300\n" "Last-Translator: Emir SARI <emir_sari@icloud.com>\n" "Language-Team: Turkish (https://github.com/bitigchi/git-po/)\n" "Language: tr\n" @@ -2408,6 +2408,18 @@ msgstr "git archive: Protokol hatası" msgid "git archive: expected a flush" msgstr "git archive: Floş bekleniyordu" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "aralıklı çıkış yüklenirken sorun" + +msgid "Minimum number of objects to request at a time" +msgstr "Bir kerede istenecek en çok nesne sayısı" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Eksik nesneleri geçerli aralıklı çıkışa sınırla" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -3149,10 +3161,6 @@ msgstr "" msgid "git version:\n" msgstr "git sürümü:\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() '%s' hatasını verip çıktı (%d)\n" - msgid "compiler info: " msgstr "derleyici bilgisi: " @@ -4158,8 +4166,91 @@ msgstr "" "clean.requireForce 'true' olarak ayarlı ve -f verilmedi; temizlik " "reddediliyor" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<seçenekler>] [--] <depo> [<dizin>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: '%s' için alternatif eklenemedi: %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "'%s' dosyasının bilgileri alınamadı" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s var ve bir dizin değil" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "'%s' bir sembolik bağ; --local ile klonlama reddediliyor" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "yineleyici '%s' üzerinden çalıştırılamadı" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "'%s' sembolik bağı var, --local ile klonlama reddediliyor" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "'%s' bağlantısı kesilemedi" + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "sabit bağlantı, '%s' konumunda denetlenemiyor" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "sabit bağlantı, '%s' konumundaki kaynaktan farklı" + +#, c-format +msgid "failed to create link '%s'" +msgstr "'%s' bağı oluşturulamadı" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "dosya şuraya kopyalanamadı: '%s'" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "'%s' üzerinde yinelenemedi" + +#, c-format +msgid "done.\n" +msgstr "bitti.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Klonlama başarılı oldu; ancak çıkış yapılamadı.\n" +"Neyin çıkış yapılıp yapılmadığını 'git status' ile inceleyebilir\n" +"ve 'git restore --source=HEAD' ile yeniden deneyebilirsiniz.\n" + +msgid "remote did not send all necessary objects" +msgstr "uzak konum gereken tüm nesneleri göndermedi" + +#, c-format +msgid "unable to update %s" +msgstr "%s güncellenemiyor" + +msgid "failed to initialize sparse-checkout" +msgstr "sparse-checkout ilklendirilemedi" + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "uzak konum HEAD'i, var olmayan başvuruya başvuruyor; çıkış yapılamıyor" + +msgid "unable to checkout working tree" +msgstr "çalışma ağacı çıkış yapılamıyor" + +msgid "unable to write parameters to config file" +msgstr "parametreler yapılandırma dosyasına yazılamıyor" + +msgid "cannot repack to clean up" +msgstr "temizlik için yeniden paketlenemiyor" + +msgid "cannot unlink temporary alternates file" +msgstr "geçici alternatifler dosyasının bağlantısı kesilemiyor" msgid "don't clone shallow repository" msgstr "sığ depoyu klonlama" @@ -4212,6 +4303,9 @@ msgstr "üstkaynağı izlemek için 'origin' yerine <ad> kullan" msgid "checkout <branch> instead of the remote's HEAD" msgstr "uzak konumun HEAD'i yerine <dal>'ı çıkış yap" +msgid "clone single revision <rev> and check out" +msgstr "tek revizyonlu <rev>'i klonla ve çıkış yap" + msgid "path to git-upload-pack on the remote" msgstr "uzak konumdaki git-upload-pack'e olan yol" @@ -4233,8 +4327,8 @@ msgstr "başvuru hariç tutarak sığ klonun geçmişini derinleştir" msgid "clone only one branch, HEAD or --branch" msgstr "yalnızca bir dal klonla, HEAD veya --branch" -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "etiket klonlama ve sonraki getirmeler de onları izlemesin" +msgid "clone tags, and make later fetches not to follow them" +msgstr "etiketleri klonla ve sonraki getirmelerin onları izlememesini sağla" msgid "any cloned submodules will be shallow" msgstr "klonlanan altmodüller sığ olacak" @@ -4277,95 +4371,8 @@ msgstr "uri" msgid "a URI for downloading bundles before fetching from origin remote" msgstr "uzak konum kökeninden getirmeden önce demetleri indirmek için bir URI" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info: '%s' için alternatif eklenemedi: %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "'%s' dosyasının bilgileri alınamadı" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s var ve bir dizin değil" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "'%s' bir sembolik bağ; --local ile klonlama reddediliyor" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "yineleyici '%s' üzerinden çalıştırılamadı" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "'%s' sembolik bağı var, --local ile klonlama reddediliyor" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "'%s' bağlantısı kesilemedi" - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "sabit bağlantı, '%s' konumunda denetlenemiyor" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "sabit bağlantı, '%s' konumundaki kaynaktan farklı" - -#, c-format -msgid "failed to create link '%s'" -msgstr "'%s' bağı oluşturulamadı" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "dosya şuraya kopyalanamadı: '%s'" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "'%s' üzerinde yinelenemedi" - -#, c-format -msgid "done.\n" -msgstr "bitti.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Klonlama başarılı oldu; ancak çıkış yapılamadı.\n" -"Neyin çıkış yapılıp yapılmadığını 'git status' ile inceleyebilir\n" -"ve 'git restore --source=HEAD' ile yeniden deneyebilirsiniz.\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Klonlanacak %s uzak dal bulunamadı." - -msgid "remote did not send all necessary objects" -msgstr "uzak konum gereken tüm nesneleri göndermedi" - -#, c-format -msgid "unable to update %s" -msgstr "%s güncellenemiyor" - -msgid "failed to initialize sparse-checkout" -msgstr "sparse-checkout ilklendirilemedi" - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "uzak konum HEAD'i, var olmayan başvuruya başvuruyor; çıkış yapılamıyor" - -msgid "unable to checkout working tree" -msgstr "çalışma ağacı çıkış yapılamıyor" - -msgid "unable to write parameters to config file" -msgstr "parametreler yapılandırma dosyasına yazılamıyor" - -msgid "cannot repack to clean up" -msgstr "temizlik için yeniden paketlenemiyor" - -msgid "cannot unlink temporary alternates file" -msgstr "geçici alternatifler dosyasının bağlantısı kesilemiyor" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<seçenekler>] [--] <depo> [<dizin>]" msgid "Too many arguments." msgstr "Çok fazla argüman." @@ -4465,6 +4472,10 @@ msgstr "uzak konum taşıması hata bildirdi" msgid "Remote branch %s not found in upstream %s" msgstr "%s uzak dalı %s üstkaynağında bulunamadı" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "%s uzak revizyonu, %s üstkaynağında bulunamadı" + msgid "You appear to have cloned an empty repository." msgstr "Boş bir depoyu klonlamış görünüyorsunuz." @@ -4641,7 +4652,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree: okunamadı" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -4651,11 +4662,11 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<kip>] [--amend]\n" -" [--dry-run] [(-c | -C | --squash) <işleme> | --fixup\n" -" [(amend|reword):]<işleme>] [-F <dosya> | -m <ileti>] [--" -"reset-author] [--allow-empty]\n" -" [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<kip>]] [--amend]\n" +" [--dry-run] [(-c | -C | --squash) <işleme> |\n" +" --fixup [(amend|reword):]<işleme>]\n" +" [-F <dosya> | -m <ileti>] [--reset-author] [--allow-empty]\n" +" [--allow-empty-message] [--no-verify] [-e] [--author=<yazar>]\n" " [--date=<tarih>] [--cleanup=<kip>] [--[no-]status]\n" " [-i | -o] [--pathspec-from-file=<dosya> [--pathspec-file-nul]]\n" " [(--trailer <jeton>[(=|:)<değer>])...] [-S[<anahtar-kimliği>]]\n" @@ -6044,15 +6055,15 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Değişikliği izlemek için 'git remote set-head %s %s' yapın veya\n" "'remote.%s.followRemoteHEAD' yapılandırma seçeneğini başka bir\n" "değere ayarlayın (bu iletiyi görmek istemiyorsanız). Özellikle\n" -"'git config set remote.%s.followRemoteHEAD %s' komutunu çalıştırmak\n" -"uyarıyı HEAD'e veya başka bir şeye uzaktan değişiklik olana dek\n" -"devre dışı bırakır." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"komutunu çalıştırmak, uyarıyı HEAD'e veya başka bir şeye uzaktan\n" +"değişiklik olana dek devre dışı bırakır." msgid "multiple branches detected, incompatible with --set-upstream" msgstr "birden çok dal algılandı, --set-upstream ile uyumsuz" @@ -6729,6 +6740,9 @@ msgstr "başka bir gc çalışıyor olsa bile zorla gc çalıştır" msgid "repack all other packs except the largest pack" msgstr "en büyük paket dışındaki diğer tüm paketleri yeniden paketle" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "budanan nesneler içeren paketi depolamak için paket öneki" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "gc.logExpiry değeri %s ayrıştırılamadı" @@ -7526,6 +7540,10 @@ msgid "Cannot come back to cwd" msgstr "Geçerli çalışma dizinine geri gelinemiyor" #, c-format +msgid "bad --pack_header: %s" +msgstr "hatalı --pack_header: %s" + +#, c-format msgid "bad %s" msgstr "hatalı %s" @@ -8384,10 +8402,6 @@ msgstr "bilinmeyen strateji seçeneği: -X%s" msgid "malformed input line: '%s'." msgstr "hatalı oluşturulmuş girdi satırı: '%s'." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "birleştirme sürdürülemiyor; %d için temiz olmayan sonuçlar alındı" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<seçenekler>] [<işleme>...]" @@ -9202,6 +9216,13 @@ msgstr "" "listesi>]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "geçersiz --name-hash-version seçeneği: %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "şu anda --write-bitmap-index, --name-hash-version=1 gerektiriyor" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -9526,6 +9547,9 @@ msgstr "" "bu protokol ile herhangi bir yapılandırılmış uploadpack.blobpackfileuri " "ögesini hariç tut" +msgid "use the specified name-hash function to group similar objects" +msgstr "benzer nesneleri gruplamak için belirtilen name-hash işlevini kullan" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "delta zincir derinliği %d çok derin, %d zorlanıyor" @@ -10756,8 +10780,8 @@ msgstr "silmek için bir başvuru günlüğü belirtilmedi" msgid "invalid ref format: %s" msgstr "geçersiz başvuru biçimi: %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<biçim> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<biçim> [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -10768,6 +10792,9 @@ msgstr "dönüştürülecek başvuru biçimini belirt" msgid "perform a non-destructive dry-run" msgstr "yıkıcı olmayan bir deneme gerçekleştir" +msgid "drop reflogs entirely during the migration" +msgstr "göç sırasında başvuru günlüklerini tümüyle bırak" + msgid "missing --ref-format=<format>" msgstr "--ref-format=<biçim> eksik" @@ -11234,8 +11261,14 @@ msgstr "Tüm itme olmayan URL'ler silinmeyecek" msgid "be verbose; must be placed before a subcommand" msgstr "ayrıntılı anlat; bir altkomuttan önce yerleştirilmelidir" -msgid "git repack [<options>]" -msgstr "git repack [<seçenekler>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<paket-adı>]\n" +"[--write-midx] [--name-hash-version=<n>]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11309,6 +11342,11 @@ msgstr "'git-pack-objects'e --no-reuse-delta geçir" msgid "pass --no-reuse-object to git-pack-objects" msgstr "'git-pack-objects'e --no-reuse-object geçir" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"benzer nesneleri yola göre gruplamada kullanılacak name-hash sürümünü belirt" + msgid "do not run git-update-server-info" msgstr "'git-update-server-info' çalıştırma" @@ -11357,9 +11395,6 @@ msgstr "<N> faktörlü bir geometrik ilerleme bul" msgid "write a multi-pack index of the resulting packs" msgstr "ortaya çıkan paketlerin bir çoklu paket indeksini yaz" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "budanan nesneler içeren paketi depolamak için paket öneki" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "süzülen nesneler içeren paketi depolamak için paket öneki" @@ -11576,9 +11611,6 @@ msgstr "-l ile yalnızca bir dizgi verilebilir" msgid "need some commits to replay" msgstr "yeniden oynatmak için birkaç işleme gerekli" -msgid "--onto and --advance are incompatible" -msgstr "--onto ve --advance birbiriyle uyumsuz" - msgid "all positive revisions given must be references" msgstr "verilen tüm pozitif revizyonlar, başvuru olmalı" @@ -14200,6 +14232,9 @@ msgstr "Git'e bir GNU Arch deposu içe aktar" msgid "Create an archive of files from a named tree" msgstr "Ad verilmiş ağaçtan bir dosyalar arşivi oluştur" +msgid "Download missing objects in a partial clone" +msgstr "Eksik nesneleri kısımsal bir klonda indir" + msgid "Use binary search to find the commit that introduced a bug" msgstr "Hatalara neden olan işlemeyi bulmada ikili arama kullan" @@ -16111,6 +16146,12 @@ msgstr "%s için geçersiz argüman" msgid "invalid regex given to -I: '%s'" msgstr "-I'ya geçersiz düzenli ifade verildi: '%s'" +msgid "-G requires a non-empty argument" +msgstr "-G, boş olmayan bir argüman gerektiriyor" + +msgid "-S requires a non-empty argument" +msgstr "-S, boş olmayan bir argüman gerektiriyor" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "--submodule seçenek parametresi ayrıştırılamadı: '%s'" @@ -18290,6 +18331,10 @@ msgid "unable to write file %s" msgstr "%s dosyası yazılamıyor" #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "sürekli olarak kaybolan %s dosyası yazılamıyor" + +#, c-format msgid "unable to set permission to '%s'" msgstr "'%s' ögesine izin ayarlanamıyor" @@ -18851,6 +18896,52 @@ msgstr "bilinmeyen anahtar '%c'" msgid "unknown non-ascii option in string: `%s'" msgstr "dizi içinde bilinmeyen ascii dışı seçenek: '%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " <%s>" + msgid "..." msgstr "..." @@ -18937,6 +19028,21 @@ msgid "failed to parse %s" msgstr "%s ayrıştırılamadı" #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "%s ağacının alt ögeleri yürütülemedi: bulunamadı" + +#, c-format +msgid "failed to find object %s" +msgstr "%s nesnesi bulunamadı" + +#, c-format +msgid "failed to find tag %s" +msgstr "%s etiketi bulunamadı" + +msgid "failed to setup revision walk" +msgstr "revizyon yürüyüşü ayarlanamadı" + +#, c-format msgid "Could not make %s writable by group" msgstr "%s grup ile yazılabilir yapılamadı" @@ -19079,6 +19185,22 @@ msgstr "vaatçi uzak konum adı '/' ile başlayamaz: %s" msgid "could not fetch %s from promisor remote" msgstr "vaatçi uzak konumundan %s getirilemedi" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "bilinen uzak konum adı '%s'; ancak url'si '%s'; '%s' olmalı" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "'%s' yapılandırma seçeneği için bilinmeyen değer: '%s'" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "uzak bilgiden bilinmeyen öge '%s'" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "kabul edilmiş vaatçi uzak konum '%s' bulunamadı" + msgid "object-info: expected flush after arguments" msgstr "object-info: argümanlardan sonra floş bekleniyordu" @@ -19902,6 +20024,14 @@ msgid "invalid refspec '%s'" msgstr "geçersiz başvuru belirteci '%s'" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "'%s' dizgisinde '*' yok" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "'%s' yedeğinde '*' yok" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "push-option değerinde geçersiz tırnak içine alım: '%s'" @@ -20021,6 +20151,31 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: git'ten bilinmeyen komut '%s'" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"Kaldırma için aday gösterilmiş \"%s/%s\" konumundan\n" +"uzak konum okunuyor.\n" +"\n" +"Eğer hâlâ \"remotes\" dizinini kullanıyorsanız\n" +"yapılandırma tabanlı uzak konumlara geçiş yapmanız\n" +"önerilir:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"Eğer geçiş yapamıyorsanız bunu neden kullandığınıza\n" +"dair bir iletiyi <git@vger.kernel.org> adresine\n" +"gönderin." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "uzak konum yapılandırma stenografisi '/' ile başlayamaz: %s" @@ -20055,14 +20210,6 @@ msgid "%s tracks both %s and %s" msgstr "%s hem %s hem %s ögelerini izler" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "dizginin '%s' anahtarında '*' yoktu" - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "dizginin '%s' değerinde '*' yok" - -#, c-format msgid "src refspec %s does not match any" msgstr "kaynak başvuru belirteci %s başka hiçbir şeyle eşleşmiyor" @@ -21948,6 +22095,27 @@ msgstr "her bir yinelemeden önce önbellek ağacını temizle" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "önbellek ağacındaki geçersizleştirilecek girdi sayısı (öntanımlı 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <seçenekler> -- <revizyon-seçenekleri>" + +msgid "toggle inclusion of blob objects" +msgstr "ikili nesnelerin içerilmesini aç/kapat" + +msgid "toggle inclusion of commit objects" +msgstr "işleme nesnelerinin içerilmesini aç/kapat" + +msgid "toggle inclusion of tag objects" +msgstr "etiket nesnelerinin içerilmesini aç/kapat" + +msgid "toggle inclusion of tree objects" +msgstr "ağaç nesnelerinin içerilmesini aç/kapat" + +msgid "toggle pruning of uninteresting paths" +msgstr "ilgisiz yolların budanmasını aç/kapat" + +msgid "read a pattern list over stdin" +msgstr "stdin'den bir dizgi listesi oku" + #, c-format msgid "commit %s is not marked reachable" msgstr "%s işlemesi ulaşılabilir olarak imlenmedi" @@ -22575,6 +22743,10 @@ msgstr "hata: " msgid "warning: " msgstr "uyarı: " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() '%s' hatasını verip çıktı (%d)\n" + msgid "Fetching objects" msgstr "Nesneler getiriliyor" @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: Git v2.46\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2025-01-04 19:26-0800\n" -"PO-Revision-Date: 2025-01-03 14:17-0800\n" +"POT-Creation-Date: 2025-03-09 15:40-0700\n" +"PO-Revision-Date: 2025-03-09 16:53-0700\n" "Last-Translator: Kateryna Golovanova <kate@kgthreads.com>\n" "Language-Team: Ukrainian <https://github.com/arkid15r/git-uk-l10n/>\n" "Language: uk\n" @@ -1433,7 +1433,7 @@ msgid "write the archive to this file" msgstr "записати архів до цього файлу" msgid "read .gitattributes in working directory" -msgstr "прочитати .gitattributes робочої директорії" +msgstr "читати .gitattributes робочої директорії" msgid "report archived files on stderr" msgstr "звітувати про заархівовані файли в stderr" @@ -2357,6 +2357,18 @@ msgstr "git archive: помилка протоколу" msgid "git archive: expected a flush" msgstr "git archive: очікувалось flush" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<н>] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "проблема із завантаженням розрідженого переходу" + +msgid "Minimum number of objects to request at a time" +msgstr "Мінімальна кількість обʼєктів для запиту за один раз" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Обмежити відсутні обʼєкти поточним розрідженим переходом" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -3117,15 +3129,11 @@ msgstr "" msgid "git version:\n" msgstr "версія git:\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() завершився невдало з помилкою \"%s\" (%d)\n" - msgid "compiler info: " msgstr "інформація щодо компілятора: " msgid "libc info: " -msgstr "информація щодо libc: " +msgstr "інформація щодо libc: " msgid "not run from a git repository - no hooks to show\n" msgstr "запущено не з git сховища - немає гачків для показу\n" @@ -3448,7 +3456,7 @@ msgid "use .gitattributes only from the index" msgstr "використовувати .gitattributes тільки з індексу" msgid "read file names from stdin" -msgstr "зчитувати назви файлів з stdin" +msgstr "читати назви файлів з stdin" msgid "terminate input and output records by a NUL character" msgstr "завершувати вхідні та вихідні записи символом NUL" @@ -3493,13 +3501,13 @@ msgid "also read contacts from stdin" msgstr "також читати контакти з stdin" msgid "read additional mailmap entries from file" -msgstr "зчитувати додаткові записи mailmap з файлу" +msgstr "читати додаткові записи mailmap з файлу" msgid "blob" msgstr "blob" msgid "read additional mailmap entries from blob" -msgstr "зчитувати додаткові записи mailmap з blob" +msgstr "читати додаткові записи mailmap з blob" msgid "no contacts specified" msgstr "контакти не вказані" @@ -3538,10 +3546,10 @@ msgid "update stat information in the index file" msgstr "оновити статистичну інформацію в індексному файлі" msgid "read list of paths from the standard input" -msgstr "зчитати список шляхів зі стандартного вводу" +msgstr "читати список шляхів зі стандартного вводу" msgid "write the content to temporary files" -msgstr "записати вміст у тимчасові файли" +msgstr "записати вміст до тимчасових файлів" msgid "copy out the files from named stage" msgstr "скопіювати файли з іменованої стадії" @@ -4146,11 +4154,94 @@ msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "" "clean.requireForce встановлено у true і -f не задано: відмовлено в прибиранні" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<опції>] [--] <сховище> [<директорія>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "інфо: Не вдалося додати запозичений обʼєкт для \"%s\": %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "не вдалося виконати stat \"%s\"" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s існує і не є директорією" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "\"%s\" є символьним посиланням, відмовлено в клонуванні з --local" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "не вдалося запустити ітератор для \"%s\"" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "символьне посилання \"%s\" існує, відмовлено в клонуванні з --local" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "не вдалося видалити \"%s\"" + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "неможливо перевірити жорстке посилання \"%s\"" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "жорстке посилання відрізняється від джерела в \"%s\"" + +#, c-format +msgid "failed to create link '%s'" +msgstr "не вдалося створити посилання \"%s\"" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "не вдалося скопіювати файл у \"%s\"" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "не вдалося здійснити перебір для \"%s\"" + +#, c-format +msgid "done.\n" +msgstr "готово.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Клонування пройшло успішно, але не вдалося перейти на гілку.\n" +"Ви можете перевірити, що було додано за допомогою 'git status'\n" +"і повторити спробу за допомогою \"git restore --source=HEAD :/\"\n" + +msgid "remote did not send all necessary objects" +msgstr "віддалене сховище не надіслало всі необхідні обʼєкти" + +#, c-format +msgid "unable to update %s" +msgstr "не вдалося оновити %s" + +msgid "failed to initialize sparse-checkout" +msgstr "не вдалося ініціалізувати розріджений перехід" + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "віддалений HEAD вказує на неіснуюче посилання, неможливо перейти" + +msgid "unable to checkout working tree" +msgstr "не вдалося завантажити стан робочої директорії" + +msgid "unable to write parameters to config file" +msgstr "не вдалося записати параметри до конфігураційного файлу" + +msgid "cannot repack to clean up" +msgstr "неможливо перепакувати для очищення" + +msgid "cannot unlink temporary alternates file" +msgstr "неможливо видалити тимчасовий файл запозичених обʼєктів" msgid "don't clone shallow repository" -msgstr "не клонувати неглибоке сховище" +msgstr "не клонувати поверхневе сховище" msgid "don't create a checkout" msgstr "не переходити на гілку" @@ -4202,6 +4293,9 @@ msgstr "" msgid "checkout <branch> instead of the remote's HEAD" msgstr "перейти до <гілки> замість HEAD віддаленого сховища" +msgid "clone single revision <rev> and check out" +msgstr "клонувати одну ревізію <rev> і перейти на неї" + msgid "path to git-upload-pack on the remote" msgstr "шлях до git-upload-pack на віддаленому сервері" @@ -4223,9 +4317,8 @@ msgstr "поглибити історію неглибокого клону, з msgid "clone only one branch, HEAD or --branch" msgstr "клонувати лише одну гілку, HEAD або --branch" -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "" -"не клонувати жодних тегів і не слідувати за ними під час отримувань пізніше" +msgid "clone tags, and make later fetches not to follow them" +msgstr "клонувати теги і більше не слідкувати за ними" msgid "any cloned submodules will be shallow" msgstr "будь-які клоновані підмодулі будуть неглибокими" @@ -4269,95 +4362,8 @@ msgstr "uri" msgid "a URI for downloading bundles before fetching from origin remote" msgstr "URI для завантаження пакунків перед отриманням з віддаленого джерела" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "инфо: Не вдалося додати запозичений обʼєкт для \"%s\": %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "не вдалося виконати stat \"%s\"" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s існує і не є директорією" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "\"%s\" є символьним посиланням, відмовлено в клонуванні з --local" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "не вдалося запустити перебір для \"%s\"" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "символьне посилання \"%s\" існує, не можу клонувати з --local" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "не вдалося видалити \"%s\"" - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "неможливо перевірити жорстке посилання \"%s\"" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "жорстке посилання відрізняється від джерела в \"%s\"" - -#, c-format -msgid "failed to create link '%s'" -msgstr "не вдалося створити посилання \"%s\"" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "не вдалося скопіювати файл у \"%s\"" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "не вдалося перебрати \"%s\"" - -#, c-format -msgid "done.\n" -msgstr "готово.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Клонування пройшло успішно, але не вдалося перейти на гілку.\n" -"Ви можете перевірити, що було додано за допомогою 'git status'\n" -"і повторити спробу за допомогою 'git restore --source=HEAD :/'\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Не вдалося знайти віддалену гілку %s для клонування." - -msgid "remote did not send all necessary objects" -msgstr "віддалене сховище не надіслало всі необхідні обʼєкти" - -#, c-format -msgid "unable to update %s" -msgstr "не вдалося оновити %s" - -msgid "failed to initialize sparse-checkout" -msgstr "не вдалося ініціалізувати розріджений перехід" - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "віддалений HEAD посилається на неіснуючого рефа, неможливо перейти" - -msgid "unable to checkout working tree" -msgstr "не вдалося завантажити стан робочої директорії" - -msgid "unable to write parameters to config file" -msgstr "не вдалося записати параметри до конфігураційного файлу" - -msgid "cannot repack to clean up" -msgstr "неможливо перепакувати, щоб очистити" - -msgid "cannot unlink temporary alternates file" -msgstr "неможливо видалити тимчасовий файл запозичених обʼєктів" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<опції>] [--] <сховище> [<директорія>]" msgid "Too many arguments." msgstr "Забагато аргументів." @@ -4463,6 +4469,10 @@ msgstr "операція віддаленого отримання повідо msgid "Remote branch %s not found in upstream %s" msgstr "Віддалену гілку %s не знайдено у першоджерельному сховищі %s" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Віддалена ревізія %s не знайдена у першоджерельному сховищі %s" + msgid "You appear to have cloned an empty repository." msgstr "Здається, ви клонували порожнє сховище." @@ -4639,7 +4649,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree: не вдалося прочитати" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -4649,7 +4659,7 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<режим>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<режим>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <коміт> | --fixup [(amend|" "reword):]<коміт>]\n" " [-F <файл> | -m <допис>] [--reset-author] [--allow-empty]\n" @@ -5214,7 +5224,7 @@ msgid "blob-id" msgstr "blob-id" msgid "read config from given blob object" -msgstr "прочитати конфігурацію з наданого blob-обʼєкту" +msgstr "читати конфігурацію з наданого blob-обʼєкту" msgid "Type" msgstr "Тип" @@ -6050,15 +6060,15 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Запустіть \"git remote set-head %s %s\", щоб відстежити зміни, або " "встановіть\n" "\"remote.%s.followRemoteHEAD\" параметр конфігурації на інше значення\n" -"якщо ви не хочете бачити це повідомлення. Зокрема, виконання команди\n" -"\"git config set remote.%s.followRemoteHEAD %s\" вимкне попередження\n" -"доки віддалений сервер не змінить HEAD на щось інше." +"якщо ви не хочете бачити це повідомлення. Зокрема, виконання\n" +"\"git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s\"\n" +"вимкне попередження, доки віддалене призначення не змінить HEAD на щось інше." msgid "multiple branches detected, incompatible with --set-upstream" msgstr "виявлено кілька гілок, несумісних з --set-upstream" @@ -6740,6 +6750,9 @@ msgstr "примусово запускати збирач сміття, нав msgid "repack all other packs except the largest pack" msgstr "перепакувати всі пакунки, крім найбільшого" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "префікс для зберігання пакунка з обрізаними обʼєктами" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "не вдалося розібрати gc.logExpiry значення %s" @@ -7120,7 +7133,7 @@ msgid "show the surrounding function" msgstr "показати навколишню функцію" msgid "read patterns from file" -msgstr "зчитувати шаблони з файлу" +msgstr "читати шаблони з файлу" msgid "match <pattern>" msgstr "зіставляти <шаблон>" @@ -7196,7 +7209,7 @@ msgid "write the object into the object database" msgstr "записати об’єкт до бази даних об’єктів" msgid "read the object from stdin" -msgstr "прочитати об’єкт з stdin" +msgstr "читати об’єкт з stdin" msgid "store file as is without filters" msgstr "зберегти файл як є без фільтрів" @@ -7548,6 +7561,10 @@ msgid "Cannot come back to cwd" msgstr "Неможливо повернутися до поточної робочої директорії" #, c-format +msgid "bad --pack_header: %s" +msgstr "невірний --pack_header: %s" + +#, c-format msgid "bad %s" msgstr "невірний %s" @@ -8420,10 +8437,6 @@ msgstr "невідомий варіант стратегії: -X%s" msgid "malformed input line: '%s'." msgstr "невірно сформований рядок вводу: \"%s\"." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "неможливо продовжити злиття; отримано брудний результат для %d" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<опції>] [<коміт>...]" @@ -9094,7 +9107,7 @@ msgid "Removing note for object %s\n" msgstr "Видалення нотатки для обʼєкта %s\n" msgid "read objects from stdin" -msgstr "зчитати обʼєкти з stdin" +msgstr "читати обʼєкти з stdin" msgid "load rewriting config for <command> (implies --stdin)" msgstr "" @@ -9216,7 +9229,7 @@ msgid "attempt to remove non-existent note is not an error" msgstr "спроба видалити неіснуючу нотатку не є помилкою" msgid "read object names from the standard input" -msgstr "зчитати імена обʼєктів зі стандартного вводу" +msgstr "читати імена обʼєктів зі стандартного вводу" msgid "do not remove, show only" msgstr "не видаляти, тільки показувати" @@ -9246,6 +9259,13 @@ msgstr "" "обʼєктів>]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "неприпустима --name-hash-version опція: %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "наразі --write-bitmap-index потребує --name-hash-version=1" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -9481,7 +9501,7 @@ msgid "do not create an empty pack output" msgstr "не створювати вивід порожнього пакунка" msgid "read revision arguments from standard input" -msgstr "зчитувати аргументи ревізії зі стандартного вводу" +msgstr "читати аргументи ревізії зі стандартного вводу" msgid "limit the objects to those that are not yet packed" msgstr "обмежувати обʼєкти тільки тими, які ще не запаковані" @@ -9570,6 +9590,10 @@ msgstr "протокол" msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "вилучити всі налаштовані uploadpack.blobpackfileuri з цим протоколом" +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"використовувати вказану name-hash функцію для групування схожих обʼєктів" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "глибина дельта ланцюжка %d занадто глибока, примусове %d" @@ -10826,8 +10850,8 @@ msgstr "не вказано журнал посилань для видален msgid "invalid ref format: %s" msgstr "неприпустимий формат посилання: %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<формат> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<формат> [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -10838,6 +10862,9 @@ msgstr "вкажіть формат посилання, в який потріб msgid "perform a non-destructive dry-run" msgstr "виконати неруйнівний пробний запуск" +msgid "drop reflogs entirely during the migration" +msgstr "повністю видалити журнал посилань під час міграції" + msgid "missing --ref-format=<format>" msgstr "відсутній --ref-format=<формат>" @@ -11312,8 +11339,14 @@ msgstr "Не видалятиме всі URL-адреси, що не є приз msgid "be verbose; must be placed before a subcommand" msgstr "розгорнутий вивід; має стояти перед підкомандою" -msgid "git repack [<options>]" -msgstr "git repack [<опції>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<н>] [--depth=<н>] [--threads=<н>] [--keep-pack=<назва-пакунка>]\n" +"[--write-midx] [--name-hash-version=<н>]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11388,6 +11421,10 @@ msgstr "передати --no-reuse-delta до git-pack-objects" msgid "pass --no-reuse-object to git-pack-objects" msgstr "передати --no-reuse-object до git-pack-objects" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "вказати версію назви хешу для групування схожих обʼєктів за шляхом" + msgid "do not run git-update-server-info" msgstr "не запускати git-update-server-info" @@ -11437,9 +11474,6 @@ msgstr "знайти геометричну прогресію з факторо msgid "write a multi-pack index of the resulting packs" msgstr "записати multi-pack-index результуючих пакунків" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "префікс для зберігання пакунка з обрізаними обʼєктами" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "префікс для зберігання пакунка з відфільтрованими обʼєктами" @@ -11656,9 +11690,6 @@ msgstr "тільки один шаблон може бути заданий з - msgid "need some commits to replay" msgstr "потрібні деякі коміти для відтворення" -msgid "--onto and --advance are incompatible" -msgstr "--onto та --advance несумісні" - msgid "all positive revisions given must be references" msgstr "всі надані позитивні ревізії мають бути посиланнями" @@ -12135,7 +12166,7 @@ msgid "use stateless RPC protocol" msgstr "використовувати протокол RPC без збереження стану" msgid "read refs from stdin" -msgstr "прочитати посилання з stdin" +msgstr "читати посилання з stdin" msgid "print status from remote helper" msgstr "вивести статус з віддаленого помічника" @@ -13623,7 +13654,7 @@ msgid "with --stdin: input lines are terminated by null bytes" msgstr "з --stdin: вхідні рядки завершуються нульовими байтами" msgid "read list of paths to be updated from standard input" -msgstr "прочитати список шляхів для оновлення зі стандартного вводу" +msgstr "читати список шляхів для оновлення зі стандартного вводу" msgid "add entries from standard input to the index" msgstr "додати записи зі стандартного вводу до індексу" @@ -14335,8 +14366,11 @@ msgstr "Імпортувати GNU Arch сховище до Git" msgid "Create an archive of files from a named tree" msgstr "Створити архів файлів з названого дерева" +msgid "Download missing objects in a partial clone" +msgstr "Завантажити відсутні обʼєкти у частковому клонуванні" + msgid "Use binary search to find the commit that introduced a bug" -msgstr "Використати бінарний пошук, щоб знайти коміт, який вніс помилку" +msgstr "Використати бінарний пошук, щоб знайти коміт, який ввів помилку" msgid "Show what revision and author last modified each line of a file" msgstr "Показати, яка ревізія та автор востаннє змінювали кожен рядок файлу" @@ -15728,7 +15762,7 @@ msgstr "помилка протоколу: неочікувані здібнос #, c-format msgid "protocol error: expected shallow sha-1, got '%s'" -msgstr "помилка протоколу: очікувалось неглибоке sha-1, отримано \"%s\"" +msgstr "помилка протоколу: очікувалось поверхневе sha-1, отримано \"%s\"" msgid "repository on the other end cannot be shallow" msgstr "сховище на іншому кінці не може бути неглибоким" @@ -16256,6 +16290,12 @@ msgstr "неприпустимий аргумент до %s" msgid "invalid regex given to -I: '%s'" msgstr "неприпустимий regex, переданий до -I: \"%s\"" +msgid "-G requires a non-empty argument" +msgstr "-G потребує непорожнього аргументу" + +msgid "-S requires a non-empty argument" +msgstr "-S потребує непорожнього аргументу" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "не вдалося розібрати параметр опції --submodule: \"%s\"" @@ -17247,7 +17287,7 @@ msgstr "" #, c-format msgid "git: '%s' is not a git command. See 'git --help'." -msgstr "git: \"%s\" не є командою git. Дивітья git --help." +msgstr "git: \"%s\" не є командою git. Дивіться git --help." msgid "Uh oh. Your system reports no Git commands at all." msgstr "Ой-ой. Ваша система повідомляє про повну відсутність Git команд." @@ -18448,6 +18488,10 @@ msgid "unable to write file %s" msgstr "не вдалося записати файл %s" #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "не вдалося записати файл %s, який постійно зникає" + +#, c-format msgid "unable to set permission to '%s'" msgstr "не вдалося встановити дозволи для \"%s\"" @@ -19020,6 +19064,52 @@ msgstr "невідомий перемикач \"%c\"" msgid "unknown non-ascii option in string: `%s'" msgstr "невідомий non-ascii параметр у рядку: \"%s\"" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " <%s>" + msgid "..." msgstr "..." @@ -19107,6 +19197,21 @@ msgid "failed to parse %s" msgstr "не вдалося розібрати %s" #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "не вдалося пройти дочірні елементи дерева %s: не знайдено" + +#, c-format +msgid "failed to find object %s" +msgstr "не вдалося знайти обʼєкт %s" + +#, c-format +msgid "failed to find tag %s" +msgstr "не вдалося знайти тег %s" + +msgid "failed to setup revision walk" +msgstr "не вдалося налаштувати проходження по ревізіям" + +#, c-format msgid "Could not make %s writable by group" msgstr "Не вдалося зробити %s доступним для запису групою" @@ -19255,6 +19360,22 @@ msgstr "назва віддаленого promisor не може починат msgid "could not fetch %s from promisor remote" msgstr "не вдалося отримати %s з віддаленого promisor" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "відоме віддалене сховище з імʼям \"%s\" має URL \"%s\" замість \"%s\"" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "невідоме значення \"%s\" для параметра конфігурації \"%s\"" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "невідомий елемент \"%s\" з віддаленої інформації" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "прийнятий віддалений promisor \"%s\" не знайдено" + msgid "object-info: expected flush after arguments" msgstr "object-info: очікувався flush після аргументів" @@ -20084,6 +20205,14 @@ msgid "invalid refspec '%s'" msgstr "неприпустимий визначник посилання \"%s\"" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "шаблон \"%s\" не має \"*\"" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "заміна \"%s\" не має \"*\"" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "неприпустимі лапки у значенні push-опції: \"%s\"" @@ -20132,7 +20261,7 @@ msgstr "віддалений сервер надіслав неочікуван msgid "unable to rewind rpc post data - try increasing http.postBuffer" msgstr "" -"не вдалося перемотати вперед rpc post дані - спробуйте збільшити " +"не вдалося перемотати вперед rpc post дані - спробуйте збільшити " "http.postBuffer" #, c-format @@ -20207,8 +20336,31 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: невідома команда \"%s\" з git" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"читання віддаленого призначення з \"%s/%s\", який номіновано на вилучення.\n" +"\n" +"Якщо ви все ще використовуєте директорію \"remotes/\", рекомендується\n" +"перейти віддалені призначення на основі конфігурації:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"Якщо ви не можете цього зробити, будь ласка, дайте нам знати, чому ви все ще " +"використовуєте її\n" +"надіславши листа на адресу <git@vger.kernel.org>." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" -msgstr "скорочення віддаленої конфігураціі не може починатися з \"/\": %s" +msgstr "скорочене ім'я віддаленої конфігураціі не може починатися з \"/\": %s" msgid "more than one receivepack given, using the first" msgstr "надано більше одного пакунка для отримання, використано перший" @@ -20241,14 +20393,6 @@ msgid "%s tracks both %s and %s" msgstr "%s відстежує як %s, так і %s" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "ключ \"%s\" шаблону не містив '*'" - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "значення \"%s\" шаблону не містить '*'" - -#, c-format msgid "src refspec %s does not match any" msgstr "визначник посилання джерела %s не збігається з жодним" @@ -22179,6 +22323,27 @@ msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "" "кількість записів у дереві кешу, які потрібно анулювати (за замовчуванням 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <опції> -- <опції-ревізії>." + +msgid "toggle inclusion of blob objects" +msgstr "перемикач включення обʼєктів blob" + +msgid "toggle inclusion of commit objects" +msgstr "перемикач включення обʼєктів коміту" + +msgid "toggle inclusion of tag objects" +msgstr "перемикач включення обʼєктів тегів" + +msgid "toggle inclusion of tree objects" +msgstr "перемикач включення обʼєктів дерева" + +msgid "toggle pruning of uninteresting paths" +msgstr "перемикач обрізання нецікавих шляхів" + +msgid "read a pattern list over stdin" +msgstr "читати список шаблонів через stdin" + #, c-format msgid "commit %s is not marked reachable" msgstr "коміт %s не позначений як досяжний" @@ -22819,6 +22984,10 @@ msgstr "помилка: " msgid "warning: " msgstr "попередження: " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() завершився невдало з помилкою \"%s\" (%d)\n" + msgid "Fetching objects" msgstr "Отримання обʼєктів" @@ -11,7 +11,7 @@ # Vũ Tiến Hưng <newcomerminecraft@gmail.com>, 2024-2025. # --- # BẢNG THUẬT NGỮ / TERMINOLOGY -# Updated: 2024-07-26, git 2.46 +# Updated: 2025-03-06, git 2.49 # # Ghi chú: # - Bảng thuật ngữ này chưa hoàn thiện. @@ -59,15 +59,17 @@ # | (v.) rebase | cải tổ | # | (v.) squash | squash | # | (v.) amend | tu bổ | +# | (n.) revision | cải biên | +# | (n.) repo/repository | kho chứa | # | | | # | ... TODO ... | | # +------------------------------------------------------------------+ msgid "" msgstr "" -"Project-Id-Version: git 2.48\n" +"Project-Id-Version: git 2.49\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-23 18:57+0000\n" -"PO-Revision-Date: 2025-01-05 01:20+0700\n" +"POT-Creation-Date: 2025-03-05 22:57+0000\n" +"PO-Revision-Date: 2025-03-06 08:20+0700\n" "Last-Translator: Vũ Tiến Hưng <newcomerminecraft@gmail.com>\n" "Language-Team: Vietnamese <https://github.com/Nekosha/git-po>\n" "Language: vi\n" @@ -1601,7 +1603,7 @@ msgid "" "git bisect cannot work properly in this case.\n" "Maybe you mistook %s and %s revs?\n" msgstr "" -"Một số điểm xét duyệt %s không phải tổ tiên của điểm xét duyệt %s.\n" +"Một số lần cải biên %s không phải tổ tiên của lần cải biên %s.\n" "git bisect không thể làm việc đúng trong trường hợp này.\n" "Liệu có phải bạn nhầm lẫn các điểm %s và %s không?\n" @@ -1621,7 +1623,7 @@ msgstr "Đang bisect: gốc hòa trộn cần phải được kiểm tra\n" #, c-format msgid "a %s revision is needed" -msgstr "cần một điểm xét duyệt %s" +msgstr "cần lần cải biên %s" #, c-format msgid "could not create file '%s'" @@ -1661,7 +1663,7 @@ msgstr[0] "(cần khoảng chừng %d bước)" #, c-format msgid "Bisecting: %d revision left to test after this %s\n" msgid_plural "Bisecting: %d revisions left to test after this %s\n" -msgstr[0] "Bisecting: còn %d điểm xét duyệt để kiểm tra %s\n" +msgstr[0] "Bisecting: còn %d lần cải biên để kiểm tra %s\n" msgid "--contents and --reverse do not blend well." msgstr "tùy chọn --contents và --reverse không nên đi với nhau." @@ -1671,7 +1673,7 @@ msgstr "" "cùng sử dụng --reverse và --first-parent cần chỉ định lần chuyển giao cuối" msgid "revision walk setup failed" -msgstr "cài đặt việc di chuyển qua các điểm xét duyệt gặp lỗi" +msgstr "cài đặt việc duyệt qua các lần cải biên gặp lỗi" msgid "" "--reverse --first-parent together require range along first-parent chain" @@ -2371,6 +2373,18 @@ msgstr "git archive: lỗi giao thức" msgid "git archive: expected a flush" msgstr "git archive: cần flush dữ liệu" +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +msgid "problem loading sparse-checkout" +msgstr "không thể tải checkout thưa" + +msgid "Minimum number of objects to request at a time" +msgstr "Số đối tượng tối thiểu mỗi lần yêu cầu" + +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Chỉ lấy về đối tượng còn thiếu trong checkout thưa hiện tại" + msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -2441,7 +2455,7 @@ msgstr "Đối số bisect_write sai: %s" #, c-format msgid "couldn't get the oid of the rev '%s'" -msgstr "không thể lấy oid của điểm xét duyệt '%s'" +msgstr "không thể lấy oid của lần cải biên '%s'" #, c-format msgid "couldn't open the file '%s'" @@ -2466,7 +2480,7 @@ msgid "" "You can use \"git bisect %s\" and \"git bisect %s\" for that." msgstr "" "Bạn cần bắt đầu bằng lệnh \"git bisect start\".\n" -"Bạn sau đó cần phải chỉ cho tôi ít nhất một điểm xét duyệt %s và một %s.\n" +"Bạn sau đó cần phải chỉ cho tôi ít nhất một lần cải biên %s và một %s.\n" "Bạn có thể sử dụng \"git bisect %s\" và \"git bisect %s\" cho chúng." #, c-format @@ -2526,7 +2540,7 @@ msgstr "không nhận ra tuỳ chọn: '%s'" #, c-format msgid "'%s' does not appear to be a valid revision" -msgstr "'%s' không có vẻ như là một điểm xét duyệt hợp lệ" +msgstr "'%s' không có vẻ như là một lần cải biên hợp lệ" msgid "bad HEAD - I need a HEAD" msgstr "sai HEAD - Tôi cần một HEAD" @@ -2587,11 +2601,11 @@ msgstr "bisect chạy gặp lỗi: không đưa ra lệnh." #, c-format msgid "unable to verify %s on good revision" -msgstr "không thể xác nhận '%s' trên điểm xét duyệt tốt" +msgstr "không thể xác nhận '%s' trên lần cải biên tốt" #, c-format msgid "bogus exit code %d for good revision" -msgstr "mã trả về %d bất thường cho điểm xét duyệt tốt" +msgstr "mã trả về %d bất thường cho lần cải biên tốt" #, c-format msgid "bisect run failed: exit code %d from %s is < 0 or >= 128" @@ -2658,7 +2672,7 @@ msgstr "phải kết thúc bằng một màu" #, c-format msgid "cannot find revision %s to ignore" -msgstr "không thể tìm thấy điểm xét duyệt %s để bỏ qua" +msgstr "không thể tìm thấy lần cải biên %s để bỏ qua" msgid "show blame entries as we find them, incrementally" msgstr "hiển thị các mục 'blame' theo thời gian, tăng dần" @@ -2717,7 +2731,7 @@ msgid "ignore <rev> when blaming" msgstr "bỏ qua <rev> khi blame" msgid "ignore revisions from <file>" -msgstr "bỏ qua các điểm xét duyệt từ <tập tin>" +msgstr "bỏ qua các lần cải biên từ <tập tin>" msgid "color redundant metadata from previous line differently" msgstr "tô màu khác cho siêu dữ liệu dư thừa từ dòng trước" @@ -2730,7 +2744,7 @@ msgstr "tiêu thụ thêm tài nguyên để tìm kiếm tốt hơn nữa" msgid "use revisions from <file> instead of calling git-rev-list" msgstr "" -"sử dụng các điểm xét duyệt (revision) từ <tập tin> thay vì gọi git-rev-list" +"sử dụng các lần cải biên (revision) từ <tập tin> thay vì gọi git-rev-list" msgid "use <file>'s contents as the final image" msgstr "sử dụng nội dung của <tập tin> như là ảnh cuối cùng" @@ -3114,10 +3128,6 @@ msgstr "" msgid "git version:\n" msgstr "phiên bản git:\n" -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() gặp lỗi '%s' (%d)\n" - msgid "compiler info: " msgstr "thông tin trình biên dịch: " @@ -3710,7 +3720,7 @@ msgstr[0] "" "\n" msgid "internal error in revision walk" -msgstr "lỗi nội bộ trong khi di chuyển qua các điểm xét duyệt" +msgstr "lỗi nội bộ trong khi di chuyển qua các lần cải biên" msgid "Previous HEAD position was" msgstr "Vị trí trước kia của HEAD là" @@ -4116,8 +4126,91 @@ msgstr "" "clean.requireForce được đặt thành true và không có tuỳ chọn -f; từ chối dọn " "dẹp" -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<các tùy chọn>] [--] <kho> [<t.mục>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "thông tin: không thể thêm thay thế cho '%s': %s\n" + +#, c-format +msgid "failed to stat '%s'" +msgstr "gặp lỗi khi stat '%s'" + +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s có tồn tại nhưng lại không phải là một thư mục" + +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "'%s' là liên kết mềm, từ chối sao chép với --local" + +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "gặp lỗi khi bắt đầu lặp qua '%s'" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "liên kết mềm '%s' đã tồn tại, từ chối sao chép với --local" + +#, c-format +msgid "failed to unlink '%s'" +msgstr "gặp lỗi khi unlink '%s'" + +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "không thể kiểm tra liên kết cứng '%s'" + +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "liên kết cứng '%s' khác với nguồn" + +#, c-format +msgid "failed to create link '%s'" +msgstr "gặp lỗi khi tạo liên kết mềm %s" + +#, c-format +msgid "failed to copy file to '%s'" +msgstr "gặp lỗi khi sao chép tập tin tới '%s'" + +#, c-format +msgid "failed to iterate over '%s'" +msgstr "gặp lỗi khi lặp qua '%s'" + +#, c-format +msgid "done.\n" +msgstr "hoàn tất.\n" + +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"Việc nhân bản thành công, nhưng checkout gặp lỗi.\n" +"Kiểm tra xem cái gì đã được checkout bằng lệnh 'git status'\n" +"và thử lại với lệnh 'git restore --source=HEAD :/'\n" + +msgid "remote did not send all necessary objects" +msgstr "máy chủ đã không gửi tất cả các đối tượng cần thiết" + +#, c-format +msgid "unable to update %s" +msgstr "không thể cập nhật %s" + +msgid "failed to initialize sparse-checkout" +msgstr "gặp lỗi khi khởi tạo sparse-checkout" + +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "HEAD ở máy chủ chỉ đến ref không tồn tại, không thể checkout" + +msgid "unable to checkout working tree" +msgstr "không thể checkout cây làm việc" + +msgid "unable to write parameters to config file" +msgstr "không thể ghi các tham số vào tập tin cấu hình" + +msgid "cannot repack to clean up" +msgstr "không thể đóng gói để dọn dẹp" + +msgid "cannot unlink temporary alternates file" +msgstr "không thể bỏ liên kết tập tin thay thế tạm thời" msgid "don't clone shallow repository" msgstr "đừng nhân bản từ kho nông" @@ -4170,6 +4263,9 @@ msgstr "dùng <tên> thay cho 'origin' để theo dõi thượng nguồn" msgid "checkout <branch> instead of the remote's HEAD" msgstr "checkout <nhánh> thay cho HEAD của máy chủ" +msgid "clone single revision <rev> and check out" +msgstr "nhân bản chỉ lần cải biên <rev> and check out" + msgid "path to git-upload-pack on the remote" msgstr "đường dẫn đến git-upload-pack trên máy chủ" @@ -4191,10 +4287,8 @@ msgstr "làm sâu hơn lịch sử của bản sao shallow, loại trừ tham ch msgid "clone only one branch, HEAD or --branch" msgstr "chỉ nhân bản một nhánh, HEAD hoặc --branch" -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "" -"đứng có nhân bản bất kỳ nhánh nào, và làm cho những lần lấy về sau không " -"theo chúng nữa" +msgid "clone tags, and make later fetches not to follow them" +msgstr "nhân bản thẻ, và làm cho những lần lấy về sau không theo chúng nữa" msgid "any cloned submodules will be shallow" msgstr "mọi mô-đun-con nhân bản sẽ là shallow (nông)" @@ -4235,95 +4329,8 @@ msgstr "uri" msgid "a URI for downloading bundles before fetching from origin remote" msgstr "URI để tải xuống bundle trước khi lấy về từ máy chủ origin" -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "thông tin: không thể thêm thay thế cho '%s': %s\n" - -#, c-format -msgid "failed to stat '%s'" -msgstr "gặp lỗi khi stat '%s'" - -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s có tồn tại nhưng lại không phải là một thư mục" - -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "'%s' là liên kết mềm, từ chối sao chép với --local" - -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "gặp lỗi khi bắt đầu lặp qua '%s'" - -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "liên kết mềm '%s' đã tồn tại, từ chối sao chép với --local" - -#, c-format -msgid "failed to unlink '%s'" -msgstr "gặp lỗi khi unlink '%s'" - -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "không thể kiểm tra liên kết cứng '%s'" - -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "liên kết cứng '%s' khác với nguồn" - -#, c-format -msgid "failed to create link '%s'" -msgstr "gặp lỗi khi tạo liên kết mềm %s" - -#, c-format -msgid "failed to copy file to '%s'" -msgstr "gặp lỗi khi sao chép tập tin tới '%s'" - -#, c-format -msgid "failed to iterate over '%s'" -msgstr "gặp lỗi khi lặp qua '%s'" - -#, c-format -msgid "done.\n" -msgstr "hoàn tất.\n" - -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"Việc nhân bản thành công, nhưng checkout gặp lỗi.\n" -"Kiểm tra xem cái gì đã được checkout bằng lệnh 'git status'\n" -"và thử lại với lệnh 'git restore --source=HEAD :/'\n" - -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "Không tìm thấy nhánh máy chủ %s để nhân bản (clone)." - -msgid "remote did not send all necessary objects" -msgstr "máy chủ đã không gửi tất cả các đối tượng cần thiết" - -#, c-format -msgid "unable to update %s" -msgstr "không thể cập nhật %s" - -msgid "failed to initialize sparse-checkout" -msgstr "gặp lỗi khi khởi tạo sparse-checkout" - -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "HEAD ở máy chủ chỉ đến ref không tồn tại, không thể checkout" - -msgid "unable to checkout working tree" -msgstr "không thể checkout cây làm việc" - -msgid "unable to write parameters to config file" -msgstr "không thể ghi các tham số vào tập tin cấu hình" - -msgid "cannot repack to clean up" -msgstr "không thể đóng gói để dọn dẹp" - -msgid "cannot unlink temporary alternates file" -msgstr "không thể bỏ liên kết tập tin thay thế tạm thời" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<các tùy chọn>] [--] <kho> [<t.mục>]" msgid "Too many arguments." msgstr "Quá nhiều đối số." @@ -4430,6 +4437,10 @@ msgstr "trình vận chuyển đã báo lỗi" msgid "Remote branch %s not found in upstream %s" msgstr "Nhánh máy chủ %s không tìm thấy trong thượng nguồn %s" +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Lần cải biên %s không tìm thấy trong thượng nguồn %s" + msgid "You appear to have cloned an empty repository." msgstr "Bạn hình như là đã nhân bản một kho trống rỗng." @@ -4605,7 +4616,7 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree: gặp lỗi khi đọc" msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -5576,7 +5587,7 @@ msgstr "" #, c-format msgid "traversed %lu commits\n" -msgstr "đã xuyên %lu qua lần chuyển giao\n" +msgstr "đã chạy qua %lu lần chuyển giao\n" #, c-format msgid "found %i tags; gave up search at %s\n" @@ -6021,8 +6032,8 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" "Chạy 'git remote set-head %s %s' để làm theo thay đổi, hoặc đặt tuỳ chọn\n" "'remote.%s.followRemoteHEAD' sang giá trị khác nếu bạn không muốn thấy\n" @@ -6073,7 +6084,7 @@ msgid "" "remote name from which new revisions should be fetched" msgstr "" "chưa chỉ ra kho chứa máy chủ; xin hãy chỉ định hoặc là URL hoặc\n" -"tên máy chủ từ cái mà những điểm xét duyệt mới có thể được fetch (lấy về)" +"tên máy chủ từ cái mà những lần cải biên mới có thể được fetch (lấy về)" msgid "you need to specify a tag name" msgstr "bạn cần chỉ định một tên thẻ" @@ -6167,7 +6178,7 @@ msgid "specify fetch refmap" msgstr "chỉ ra refmap cần lấy về" msgid "revision" -msgstr "điểm xét duyệt" +msgstr "lần cải biên" msgid "report that we have only objects reachable from this object" msgstr "báo rằng ta chỉ có các đối tượng tiếp cận được từ đối tượng này" @@ -6705,6 +6716,9 @@ msgstr "buộc gc chạy ngay cả khi có tiến trình gc khác đang chạy" msgid "repack all other packs except the largest pack" msgstr "đóng gói lại tất cả các gói khác ngoại trừ gói lớn nhất" +msgid "pack prefix to store a pack containing pruned objects" +msgstr "tiền tố của gói để lưu gói gồm những đối tượng đã loại bỏ" + #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "gặp lỗi khi đọc giá trị gc.logExpiry %s" @@ -7113,7 +7127,7 @@ msgstr "--no-index hay --untracked không được sử dụng cùng với revs" #, c-format msgid "unable to resolve revision: %s" -msgstr "không thể phân giải điểm xét duyệt: %s" +msgstr "không thể phân giải lần cải biên: %s" msgid "--untracked not supported with --recurse-submodules" msgstr "tùy chọn --untracked không được hỗ trợ với --recurse-submodules" @@ -7491,6 +7505,10 @@ msgid "Cannot come back to cwd" msgstr "Không thể quay lại thư mục hiện hành" #, c-format +msgid "bad --pack_header: %s" +msgstr "--pack_header sai: %s" + +#, c-format msgid "bad %s" msgstr "%s sai" @@ -7758,10 +7776,10 @@ msgid "failed to find exact merge base" msgstr "gặp lỗi khi tìm gốc hòa trộn chính xác" msgid "base commit should be the ancestor of revision list" -msgstr "lần chuyển giao nền không là tổ tiên của danh sách điểm xét duyệt" +msgstr "lần chuyển giao nền không là tổ tiên của danh sách lần cải biên" msgid "base commit shouldn't be in revision list" -msgstr "lần chuyển giao nền không được trong danh sách điểm xét duyệt" +msgstr "lần chuyển giao nền không được trong danh sách lần cải biên" msgid "cannot get patch id" msgstr "không thể lấy mã bản vá" @@ -8356,10 +8374,6 @@ msgstr "không hiểu chiến lược: -X%s" msgid "malformed input line: '%s'." msgstr "dòng đầu vào sai quy cách: '%s'." -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "không thể tiếp tục hoà trộn; kết quả không hoàn toàn %d" - msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<các tùy chọn>] [<commit>...]" @@ -9187,6 +9201,13 @@ msgstr "" "sách-đối-tượng>]" #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "tùy chọn --name-hash-version không hợp lệ: %d" + +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "--write-bitmap-index hiện cần --name-hash-version=1" + +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -9363,7 +9384,7 @@ msgstr "không phải một rev '%s'" #, c-format msgid "bad revision '%s'" -msgstr "điểm xem xét sai '%s'" +msgstr "lần cải biên sai '%s'" msgid "unable to add recent objects" msgstr "không thể thêm các đối tượng mới dùng" @@ -9509,6 +9530,9 @@ msgstr "giao thức" msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "loại trừ bất kỳ cấu hình uploadpack.blobpackfileuri với giao thức này" +msgid "use the specified name-hash function to group similar objects" +msgstr "dùng hàm băm này để nhóm các đối tượng giống nhau" + #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "mức delta chain %d là quá sâu, buộc dùng %d" @@ -10261,7 +10285,7 @@ msgid "" msgstr "" "\n" "git gặp phải một lỗi trong khi đang chuẩn bị các bản vá để diễn lại\n" -"những điểm xét duyệt này:\n" +"những lần cải biên này:\n" "\n" " %s\n" "\n" @@ -10750,8 +10774,8 @@ msgstr "chưa chỉ ra reflog để xóa" msgid "invalid ref format: %s" msgstr "định dạng tham chiếu không hợp lệ: %s" -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<định dạng> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<định dạng> [--no-reflog] [--dry-run]" msgid "git refs verify [--strict] [--verbose]" msgstr "git refs verify [--strict] [--verbose]" @@ -10762,6 +10786,9 @@ msgstr "chỉ định định dạng tham chiếu để chuyển đổi sang" msgid "perform a non-destructive dry-run" msgstr "chạy thử mà không thay đổi gì" +msgid "drop reflogs entirely during the migration" +msgstr "bỏ reflog khi chuyển đổi" + msgid "missing --ref-format=<format>" msgstr "thiếu --ref-format=<định dạng>" @@ -11216,8 +11243,14 @@ msgstr "Sẽ không xóa những địa chỉ URL không-push" msgid "be verbose; must be placed before a subcommand" msgstr "chi tiết; phải được đặt trước một lệnh-con" -msgid "git repack [<options>]" -msgstr "git repack [<các tùy chọn>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<tên-pack>]\n" +"[--write-midx] [--name-hash-version=<n>]" msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" @@ -11293,6 +11326,10 @@ msgstr "chuyển --no-reuse-delta cho git-pack-objects" msgid "pass --no-reuse-object to git-pack-objects" msgstr "chuyển --no-reuse-object cho git-pack-objects" +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "phiên bản hàm băm để nhóm đối tượng giống nhau theo đường dẫn" + msgid "do not run git-update-server-info" msgstr "không chạy git-update-server-info" @@ -11341,9 +11378,6 @@ msgstr "tìm một tiến trình hình học với hệ số <N>" msgid "write a multi-pack index of the resulting packs" msgstr "ghi chỉ mục 'multi-pack' của các gói kết quả" -msgid "pack prefix to store a pack containing pruned objects" -msgstr "tiền tố của gói để lưu gói gồm những đối tượng đã loại bỏ" - msgid "pack prefix to store a pack containing filtered out objects" msgstr "tiền tố của gói để lưu gói gồm những đối tượng đã lọc bỏ" @@ -11560,11 +11594,8 @@ msgstr "chỉ được chỉ định một mẫu cùng với tùy chọn -l" msgid "need some commits to replay" msgstr "cần các chuyển giao để phát lại" -msgid "--onto and --advance are incompatible" -msgstr "--onto và --advance xung khắc" - msgid "all positive revisions given must be references" -msgstr "mọi điểm xét duyệt cộng thêm phải là tên tham chiếu" +msgstr "mọi lần cải biên cộng thêm phải là tên tham chiếu" msgid "argument to --advance must be a reference" msgstr "tham số cho --advance phải là tham chiếu" @@ -11610,11 +11641,11 @@ msgid "" "some rev walking options will be overridden as '%s' bit in 'struct rev_info' " "will be forced" msgstr "" -"một số tuỳ chọn duyệt qua điểm xét duyệt sẽ bị bỏ qua do bit '%s' trong " +"một số tuỳ chọn duyệt qua lần cải biên sẽ bị bỏ qua do bit '%s' trong " "'struct rev_info' bị ép bật/tắt" msgid "error preparing revisions" -msgstr "gặp lỗi khi chuẩn bị các điểm xét duyệt" +msgstr "gặp lỗi khi chuẩn bị các lần cải biên" msgid "replaying down to root commit is not supported yet!" msgstr "chưa hỗ trợ phát lại đến lần chuyển giao gốc!" @@ -11709,7 +11740,7 @@ msgstr "chỉ ghi lại những đường dẫn thực sự sẽ được thêm #, c-format msgid "Failed to resolve '%s' as a valid revision." -msgstr "Gặp lỗi khi phân giải '%s' thành điểm xét duyệt hợp lệ." +msgstr "Gặp lỗi khi phân giải '%s' thành lần cải biên hợp lệ." #, c-format msgid "Failed to resolve '%s' as a valid tree." @@ -11742,7 +11773,7 @@ msgstr "" #, c-format msgid "Could not reset index file to revision '%s'." -msgstr "Không thể đặt lại (reset) chỉ mục thành điểm xét duyệt '%s'." +msgstr "Không thể đặt lại (reset) chỉ mục thành lần cải biên '%s'." msgid "Could not write new index file." msgstr "Không thể ghi tập tin chỉ mục mới." @@ -11784,7 +11815,7 @@ msgid "missing opt-spec before option flags" msgstr "thiếu opt-spec trước các tuỳ chọn" msgid "Needed a single revision" -msgstr "Cần một điểm xét duyệt đơn" +msgstr "Cần một lần cải biên đơn" msgid "" "git rev-parse --parseopt [<options>] -- [<args>...]\n" @@ -12160,7 +12191,7 @@ msgstr "không có tham chiếu nào như thế %s" #, c-format msgid "cannot handle more than %d rev." msgid_plural "cannot handle more than %d revs." -msgstr[0] "không thể xử lý nhiều hơn %d điểm xét duyệt." +msgstr[0] "không thể xử lý nhiều hơn %d lần cải biên." #, c-format msgid "'%s' is not a valid ref." @@ -12438,7 +12469,7 @@ msgstr "'%s' không phải là lần chuyển giao kiểu-stash" #, c-format msgid "Too many revisions specified:%s" -msgstr "Chỉ ra quá nhiều điểm xét duyệt: %s" +msgstr "Chỉ ra quá nhiều lần cải biên: %s" msgid "No stash entries found." msgstr "Không tìm thấy các mục tạm cất (stash) nào." @@ -12742,7 +12773,7 @@ msgstr "" "dẫn>]" msgid "could not fetch a revision for HEAD" -msgstr "không thể lấy về một điểm xem xét cho HEAD" +msgstr "không thể lấy về một lần cải biên cho HEAD" #, c-format msgid "Synchronizing submodule url for '%s'\n" @@ -12977,8 +13008,7 @@ msgstr "" #, c-format msgid "Unable to find current revision in submodule path '%s'" -msgstr "" -"Không tìm thấy điểm xét duyệt hiện hành trong đường dẫn mô-đun-con '%s'" +msgstr "Không tìm thấy lần cải biên hiện hành trong đường dẫn mô-đun-con '%s'" #, c-format msgid "Unable to fetch in submodule path '%s'" @@ -12986,7 +13016,7 @@ msgstr "Không thể lấy về trong đường dẫn mô-đun-con '%s'" #, c-format msgid "Unable to find %s revision in submodule path '%s'" -msgstr "Không tìm thấy điểm xét duyệt %s trong đường dẫn mô-đun-con '%s'" +msgstr "Không tìm thấy lần cải biên %s trong đường dẫn mô-đun-con '%s'" #, c-format msgid "Failed to recurse into submodule path '%s'" @@ -13017,8 +13047,7 @@ msgid "use the 'rebase' update strategy" msgstr "dùng chiến lược hòa trộn 'rebase'" msgid "create a shallow clone truncated to the specified number of revisions" -msgstr "" -"tạo một bản sao nông được cắt ngắn thành số lượng điểm xét duyệt đã cho" +msgstr "tạo một bản sao nông được cắt ngắn thành số lượng lần cải biên đã cho" msgid "parallel jobs" msgstr "công việc đồng thời" @@ -14190,6 +14219,9 @@ msgstr "Nhập một kho GNU Arch vào một kho Git" msgid "Create an archive of files from a named tree" msgstr "Tạo một kho nén các tập tin từ cây làm việc có tên" +msgid "Download missing objects in a partial clone" +msgstr "Tải về các đối tượng còn thiếu khi nhân bản một phần" + msgid "Use binary search to find the commit that introduced a bug" msgstr "Tìm kiếm dạng nhị phân để tìm ra lần chuyển giao nào đưa ra lỗi" @@ -14727,7 +14759,7 @@ msgid "Git Repository Layout" msgstr "Bố cục kho Git" msgid "Specifying revisions and ranges for Git" -msgstr "Chỉ định điểm xét duyệt và vùng cho Git" +msgstr "Chỉ định lần cải biên và vùng cho Git" msgid "Mounting one repository inside another" msgstr "Gắn một kho chứa vào trong một cái khác" @@ -15482,7 +15514,7 @@ msgstr "tham chiếu '%s' không chỉ đến một blob nào cả" #, c-format msgid "unable to resolve config blob '%s'" -msgstr "không thể phân giải điểm xét duyệt '%s'" +msgstr "không thể phân giải lần cải biên '%s'" msgid "unable to parse command-line config" msgstr "không thể đọc cấu hình dòng lệnh" @@ -16106,6 +16138,12 @@ msgstr "tham số cho %s không hợp lệ" msgid "invalid regex given to -I: '%s'" msgstr "đưa cho -I biểu thức chính quy không hợp lệ: '%s'" +msgid "-G requires a non-empty argument" +msgstr "-G cần một tham số" + +msgid "-S requires a non-empty argument" +msgstr "-S cần một tham số" + #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "gặp lỗi khi đọc đối số tùy chọn --submodule: '%s'" @@ -18275,6 +18313,10 @@ msgid "unable to write file %s" msgstr "không thể ghi tập tin %s" #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "không thể ghi vào tập tin biến mất liên tục %s" + +#, c-format msgid "unable to set permission to '%s'" msgstr "không thể đặt quyền thành '%s'" @@ -18735,7 +18777,7 @@ msgstr "checksum không hợp lệ" #, c-format msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>" -msgstr "vị trí mục xét duyệt không hợp lệ %<PRIu64>: %<PRIu32> != %<PRIu32>" +msgstr "vị trí mục cải biên không hợp lệ %<PRIu64>: %<PRIu32> != %<PRIu32>" msgid "multi-pack-index reverse-index chunk is the wrong size" msgstr "chunk chỉ mục ngược của chỉ mục đa gói có kích thước sai" @@ -18833,6 +18875,52 @@ msgstr "không hiểu tùy chọn '%c'" msgid "unknown non-ascii option in string: `%s'" msgstr "không hiểu tùy chọn non-ascii trong chuỗi: '%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#, c-format +msgid " <%s>" +msgstr " <%s>" + msgid "..." msgstr "..." @@ -18920,6 +19008,21 @@ msgid "failed to parse %s" msgstr "gặp lỗi khi đọc cú pháp %s" #, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "gặp lỗi khi duyệt nhánh của cây %s: không tìm thấy" + +#, c-format +msgid "failed to find object %s" +msgstr "gặp lỗi khi tìm đối tượng '%s'." + +#, c-format +msgid "failed to find tag %s" +msgstr "gặp lỗi khi tìm thẻ %s" + +msgid "failed to setup revision walk" +msgstr "gặp lỗi khi thiết lập duyệt lần cải biên" + +#, c-format msgid "Could not make %s writable by group" msgstr "Không thể làm %s được ghi bởi nhóm" @@ -19063,6 +19166,22 @@ msgstr "tên máy chủ promisor không thể bắt đầu bằng '/': %s" msgid "could not fetch %s from promisor remote" msgstr "không thể tải %s từ máy chủ promisor" +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "có máy chủ '%s' nhưng với url '%s' thay vì '%s'" + +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "không hiểu giá trị '%s' cho cho cấu hình '%s'" + +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "không hiểu phần '%s' từ thông tin máy chủ" + +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "không tìm thấy accepted promisor remote '%s'" + msgid "object-info: expected flush after arguments" msgstr "object-info: cần đẩy dữ liệu lên đĩa sau các tham số" @@ -19750,7 +19869,7 @@ msgid "refusing to update ref with bad name '%s'" msgstr "từ chối cập nhật tham chiếu với tên sai '%s'" msgid "refusing to force and skip creation of reflog" -msgstr "từ chối bỏ qua việc tạo log tham chiếu" +msgstr "từ chối bỏ qua việc tạo reflog" #, c-format msgid "update_ref failed for ref '%s': %s" @@ -19884,6 +20003,14 @@ msgid "invalid refspec '%s'" msgstr "refspec không hợp lệ '%s'" #, c-format +msgid "pattern '%s' has no '*'" +msgstr "giá trị '%s' không có '*'" + +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "thay thế '%s' không có '*'" + +#, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "sai trích dẫn trong giá trị push-option :'%s'" @@ -20003,6 +20130,27 @@ msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: không hiểu lệnh '%s' từ git" #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"đang đọc máy chủ từ \"%s/%s\", đã được đề cử để loại bỏ.\n" +"Nếu bạn vẫn còn sử dụng thư mục \"remotes\", chúng tôi khuyên bạn\n" +"hãy chuyển đổi sang sử dụng máy chủ qua tập tin cấu hình:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"Nếu bạn không thể đổi, hãy cho chúng tôi biết tại sao bạn cần nó\n" +"bằng cách gửi e-mail đến <git@vger.kernel.org>." + +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "cấu hình viết tắt máy chủ không thể bắt đầu bằng '/': %s" @@ -20037,14 +20185,6 @@ msgid "%s tracks both %s and %s" msgstr "%s theo dõi cả %s và %s" #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "khóa '%s' của mẫu k có '*'" - -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "giá trị '%s' của mẫu k có '*'" - -#, c-format msgid "src refspec %s does not match any" msgstr "refspec (đặc tả tham chiếu) nguồn %s không khớp bất kỳ cái gì" @@ -20317,7 +20457,7 @@ msgid "update the index with reused conflict resolution if possible" msgstr "cập nhật chỉ mục với phân giải xung đột dùng lại nếu được" msgid "could not determine HEAD revision" -msgstr "không thể dò tìm điểm xét duyệt HEAD" +msgstr "không thể dò tìm lần cải biên HEAD" #, c-format msgid "failed to find tree of %s" @@ -21456,10 +21596,10 @@ msgid "" "Use '--' to separate paths from revisions, like this:\n" "'git <command> [<revision>...] -- [<file>...]'" msgstr "" -"tham số chưa rõ ràng '%s': chưa biết điểm xét duyệt hay đường dẫn không " -"trong cây làm việc.\n" -"Dùng '--' để ngăn cách các đường dẫn khỏi điểm xét duyệt, như thế này:\n" -"'git <lệnh> [<điểm xét duyệt>...] -- [<tập tin>...]'" +"tham số chưa rõ ràng '%s': chưa biết lần cải biên hay đường dẫn không trong " +"cây làm việc.\n" +"Dùng '--' để ngăn cách các đường dẫn khỏi lần cải biên, như thế này:\n" +"'git <lệnh> [<lần cải biên>...] -- [<tập tin>...]'" #, c-format msgid "option '%s' must come before non-option arguments" @@ -21471,9 +21611,9 @@ msgid "" "Use '--' to separate paths from revisions, like this:\n" "'git <command> [<revision>...] -- [<file>...]'" msgstr "" -"tham số chưa rõ ràng '%s': cả điểm xem xét và tên tập tin.\n" -"Dùng '--' để ngăn cách các đường dẫn khỏi điểm xem xét, như thế này:\n" -"'git <lệnh> [<điểm xem xét>...] -- [<tập tin>...]'" +"tham số chưa rõ ràng '%s': cả lần cải biên và tên tập tin.\n" +"Dùng '--' để ngăn cách các đường dẫn khỏi lần cải biên, như thế này:\n" +"'git <lệnh> [<lần cải biên>...] -- [<tập tin>...]'" msgid "unable to set up work tree using invalid config" msgstr "không thể thiết lập thư mục làm việc với cấu hình không hợp lệ" @@ -21935,6 +22075,27 @@ msgstr "dọn cây nhớ tạm trước mỗi chu kỳ" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "số mục cần huỷ trong câu nhớ tạm (mặc định 0)" +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <tuỳ chọn> -- <tuỳ chọn cải biên>" + +msgid "toggle inclusion of blob objects" +msgstr "bao gồm các đối tượng blob" + +msgid "toggle inclusion of commit objects" +msgstr "bao gồm các đối tượng chuyển giao" + +msgid "toggle inclusion of tag objects" +msgstr "bao gồm các đối tượng thẻ" + +msgid "toggle inclusion of tree objects" +msgstr "bao gồm các đối tượng cây" + +msgid "toggle pruning of uninteresting paths" +msgstr "lược bỏ những đường dẫn ít ý nghĩa" + +msgid "read a pattern list over stdin" +msgstr "đọc các mẫu từ stdin" + #, c-format msgid "commit %s is not marked reachable" msgstr "lần chuyển giao %s chưa được đánh dấu là tiếp cận được" @@ -22579,6 +22740,10 @@ msgstr "lỗi: " msgid "warning: " msgstr "cảnh báo: " +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() gặp lỗi '%s' (%d)\n" + msgid "Fetching objects" msgstr "Đang lấy về các đối tượng" @@ -23536,3 +23701,21 @@ msgstr "Bỏ qua %s với hậu tố sao lưu '%s'.\n" #, perl-format msgid "Do you really want to send %s? [y|N]: " msgstr "Bạn có thực sự muốn gửi %s? [y|N](có/KHÔNG): " + +#, c-format +#~ msgid "Could not find remote branch %s to clone." +#~ msgstr "Không tìm thấy nhánh máy chủ %s để nhân bản (clone)." + +#, c-format +#~ msgid "merging cannot continue; got unclean result of %d" +#~ msgstr "không thể tiếp tục hoà trộn; kết quả không hoàn toàn %d" + +#~ msgid "git repack [<options>]" +#~ msgstr "git repack [<các tùy chọn>]" + +#~ msgid "--onto and --advance are incompatible" +#~ msgstr "--onto và --advance xung khắc" + +#, c-format +#~ msgid "key '%s' of pattern had no '*'" +#~ msgstr "khóa '%s' của mẫu k có '*'" diff --git a/po/zh_CN.po b/po/zh_CN.po index 12a0fb510b..5cde4011e7 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -93,6 +93,7 @@ # pack index | 包索引 # packfile | 包文件 # parent | 父提交 +# partial clone | 部分克隆 # patch | 补丁 # pathspec | 路径规格 # pattern | 模式 @@ -154,8 +155,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2025-01-02 20:43+0800\n" -"PO-Revision-Date: 2025-01-05 19:01+0800\n" +"POT-Creation-Date: 2025-03-09 20:34+0800\n" +"PO-Revision-Date: 2025-03-12 14:47+0800\n" "Last-Translator: Teng Long <dyroneteng@gmail.com>\n" "Language-Team: GitHub <https://github.com/dyrone/git/>\n" "Language: zh_CN\n" @@ -2962,6 +2963,22 @@ msgstr "git archive:协议错误" msgid "git archive: expected a flush" msgstr "git archive:应有一个 flush 包" +#: builtin/backfill.c +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +#: builtin/backfill.c +msgid "problem loading sparse-checkout" +msgstr "加载稀疏检出时出现问题" + +#: builtin/backfill.c +msgid "Minimum number of objects to request at a time" +msgstr "单次请求的最少对象数量" + +#: builtin/backfill.c +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "将缺少的对象限制在当前的稀疏检出中" + #: builtin/bisect.c msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" @@ -3381,7 +3398,7 @@ msgstr "显示作者的邮箱而不是名字(默认:关闭)" msgid "ignore whitespace differences" msgstr "忽略空白差异" -#: builtin/blame.c builtin/log.c +#: builtin/blame.c builtin/clone.c builtin/log.c msgid "rev" msgstr "版本" @@ -3803,8 +3820,8 @@ msgstr "HEAD 没有位于 /refs/heads 之下!" #: builtin/branch.c msgid "" -"branch with --recurse-submodules can only be used if submodule." -"propagateBranches is enabled" +"branch with --recurse-submodules can only be used if " +"submodule.propagateBranches is enabled" msgstr "" "带有 --recurse-submodules 的分支只能在 submodule.propagateBranches 启用时使用" @@ -3892,11 +3909,6 @@ msgid "git version:\n" msgstr "git 版本:\n" #: builtin/bugreport.c -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() 失败,错误为 '%s'(%d)\n" - -#: builtin/bugreport.c msgid "compiler info: " msgstr "编译器信息:" @@ -5134,8 +5146,112 @@ msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "clean.requireForce 设置为 true 且未提供 -f 选项:拒绝执行清理动作" #: builtin/clone.c -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<选项>] [--] <仓库> [<路径>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: 不能为 '%s' 添加一个备用:%s\n" + +#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c +#, c-format +msgid "failed to stat '%s'" +msgstr "无法对 '%s' 调用 stat" + +#: builtin/clone.c +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s 存在且不是一个目录" + +#: builtin/clone.c +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "'%s' 为符号链接,拒绝用 --local 克隆" + +#: builtin/clone.c +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "无法在 '%s' 上启动迭代器" + +#: builtin/clone.c +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "符号链接 '%s' 存在,拒绝用 --local 克隆" + +#: builtin/clone.c compat/precompose_utf8.c +#, c-format +msgid "failed to unlink '%s'" +msgstr "无法删除 '%s'" + +#: builtin/clone.c +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "无法检查 '%s' 处的硬链接" + +#: builtin/clone.c +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "硬链接与 '%s' 处的来源不同" + +#: builtin/clone.c +#, c-format +msgid "failed to create link '%s'" +msgstr "无法创建链接 '%s'" + +#: builtin/clone.c +#, c-format +msgid "failed to copy file to '%s'" +msgstr "无法拷贝文件至 '%s'" + +#: builtin/clone.c refs/files-backend.c +#, c-format +msgid "failed to iterate over '%s'" +msgstr "无法在 '%s' 上迭代" + +#: builtin/clone.c +#, c-format +msgid "done.\n" +msgstr "完成。\n" + +#: builtin/clone.c +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"克隆成功,但是检出失败。\n" +"您可以通过 'git status' 检查哪些已被检出,然后使用命令\n" +"'git restore --source=HEAD :/' 重试\n" + +#: builtin/clone.c fetch-pack.c +msgid "remote did not send all necessary objects" +msgstr "远程没有发送所有必需的对象" + +#: builtin/clone.c +#, c-format +msgid "unable to update %s" +msgstr "不能更新 %s" + +#: builtin/clone.c +msgid "failed to initialize sparse-checkout" +msgstr "无法初始化稀疏检出" + +#: builtin/clone.c +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "远程 HEAD 指向一个不存在的引用,无法检出" + +#: builtin/clone.c +msgid "unable to checkout working tree" +msgstr "不能检出工作区" + +#: builtin/clone.c +msgid "unable to write parameters to config file" +msgstr "无法将参数写入配置文件" + +#: builtin/clone.c +msgid "cannot repack to clean up" +msgstr "无法执行 repack 来清理" + +#: builtin/clone.c +msgid "cannot unlink temporary alternates file" +msgstr "无法删除临时的备用文件" #: builtin/clone.c msgid "don't clone shallow repository" @@ -5208,6 +5324,10 @@ msgid "checkout <branch> instead of the remote's HEAD" msgstr "检出 <分支> 而不是远程 HEAD" #: builtin/clone.c +msgid "clone single revision <rev> and check out" +msgstr "克隆单个版本 <版本> 并检出" + +#: builtin/clone.c msgid "path to git-upload-pack on the remote" msgstr "远程 git-upload-pack 路径" @@ -5236,8 +5356,8 @@ msgid "clone only one branch, HEAD or --branch" msgstr "只克隆一个分支、HEAD 或 --branch" #: builtin/clone.c -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "不要克隆任何标签,并且后续获取操作也不下载它们" +msgid "clone tags, and make later fetches not to follow them" +msgstr "克隆标签,并在后续获取时不跟随它们" #: builtin/clone.c msgid "any cloned submodules will be shallow" @@ -5294,117 +5414,8 @@ msgid "a URI for downloading bundles before fetching from origin remote" msgstr "用于在从 origin 远程获取之前下载归档包的 URI" #: builtin/clone.c -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info: 不能为 '%s' 添加一个备用:%s\n" - -#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c -#, c-format -msgid "failed to stat '%s'" -msgstr "无法对 '%s' 调用 stat" - -#: builtin/clone.c -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s 存在且不是一个目录" - -#: builtin/clone.c -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "'%s' 为符号链接,拒绝用 --local 克隆" - -#: builtin/clone.c -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "无法在 '%s' 上启动迭代器" - -#: builtin/clone.c -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "符号链接 '%s' 存在,拒绝用 --local 克隆" - -#: builtin/clone.c compat/precompose_utf8.c -#, c-format -msgid "failed to unlink '%s'" -msgstr "无法删除 '%s'" - -#: builtin/clone.c -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "无法检查 '%s' 处的硬链接" - -#: builtin/clone.c -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "硬链接与 '%s' 处的源不同" - -#: builtin/clone.c -#, c-format -msgid "failed to create link '%s'" -msgstr "无法创建链接 '%s'" - -#: builtin/clone.c -#, c-format -msgid "failed to copy file to '%s'" -msgstr "无法拷贝文件至 '%s'" - -#: builtin/clone.c refs/files-backend.c -#, c-format -msgid "failed to iterate over '%s'" -msgstr "无法在 '%s' 上迭代" - -#: builtin/clone.c -#, c-format -msgid "done.\n" -msgstr "完成。\n" - -#: builtin/clone.c -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"克隆成功,但是检出失败。\n" -"您可以通过 'git status' 检查哪些已被检出,然后使用命令\n" -"'git restore --source=HEAD :/' 重试\n" - -#: builtin/clone.c -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "不能发现要克隆的远程分支 %s。" - -#: builtin/clone.c fetch-pack.c -msgid "remote did not send all necessary objects" -msgstr "远程没有发送所有必需的对象" - -#: builtin/clone.c -#, c-format -msgid "unable to update %s" -msgstr "不能更新 %s" - -#: builtin/clone.c -msgid "failed to initialize sparse-checkout" -msgstr "无法初始化稀疏检出" - -#: builtin/clone.c -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "远程 HEAD 指向一个不存在的引用,无法检出" - -#: builtin/clone.c -msgid "unable to checkout working tree" -msgstr "不能检出工作区" - -#: builtin/clone.c -msgid "unable to write parameters to config file" -msgstr "无法将参数写入配置文件" - -#: builtin/clone.c -msgid "cannot repack to clean up" -msgstr "无法执行 repack 来清理" - -#: builtin/clone.c -msgid "cannot unlink temporary alternates file" -msgstr "无法删除临时的 alternates 文件" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<选项>] [--] <仓库> [<目录>]" #: builtin/clone.c msgid "Too many arguments." @@ -5531,6 +5542,11 @@ msgid "Remote branch %s not found in upstream %s" msgstr "远程分支 %s 在上游 %s 未发现" #: builtin/clone.c +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "在上游 %2$s 未发现远程版本 %1$s" + +#: builtin/clone.c msgid "You appear to have cloned an empty repository." msgstr "您似乎克隆了一个空仓库。" @@ -5593,7 +5609,8 @@ msgstr "" "[no-]progress]\n" " <切分选项>" -#: builtin/commit-graph.c builtin/fetch.c builtin/log.c builtin/repack.c +#: builtin/commit-graph.c builtin/fetch.c builtin/gc.c builtin/log.c +#: builtin/repack.c msgid "dir" msgstr "目录" @@ -5751,7 +5768,7 @@ msgstr "git commit-tree:无法读取" #: builtin/commit.c msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -5761,7 +5778,7 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<模式>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<模式>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <提交> | --fixup [(amend|" "reword):]<提交>]\n" " [-F <文件> | -m <消息>] [--reset-author] [--allow-empty]\n" @@ -7473,14 +7490,13 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" -"运行 'git remote set-head %s %s' 以跟随更改,或者\n" -"如果您不想看到此消息,则将'remote.%s.followRemoteHEAD' 配置选项设置为不同的" -"值。\n" -"特别地,运行 'git config set remote.%s.followRemoteHEAD %s' 将禁用警告,直到" -"远程将 HEAD 更改为其他内容。\"" +"运行 'git remote set-head %s %s' 同步变更,或通过配置选项\n" +"'remote.%s.followRemoteHEAD' 设置为其他值以屏蔽此提示。具体可通过\n" +"运行命令 'git config remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"以禁用该警告,直到远程将 HEAD 更改为其他内容。" #: builtin/fetch.c msgid "multiple branches detected, incompatible with --set-upstream" @@ -7721,8 +7737,8 @@ msgstr "协议不支持 --negotiate-only,退出" #: builtin/fetch.c msgid "" -"--filter can only be used with the remote configured in extensions." -"partialclone" +"--filter can only be used with the remote configured in " +"extensions.partialclone" msgstr "只可以将 --filter 用于在 extensions.partialclone 中配置的远程仓库" #: builtin/fetch.c @@ -8328,6 +8344,10 @@ msgstr "强制执行 gc 即使另外一个 gc 正在执行" msgid "repack all other packs except the largest pack" msgstr "除了最大的包之外,对所有其它包文件重新打包" +#: builtin/gc.c builtin/repack.c +msgid "pack prefix to store a pack containing pruned objects" +msgstr "用于存储修剪对象的包前缀" + #: builtin/gc.c #, c-format msgid "failed to parse gc.logExpiry value %s" @@ -9327,6 +9347,11 @@ msgstr "无法完成 pack-objects 来重新打包本地链接" msgid "Cannot come back to cwd" msgstr "无法返回当前工作目录" +#: builtin/index-pack.c builtin/unpack-objects.c +#, c-format +msgid "bad --pack_header: %s" +msgstr "错误的 --pack_header:%s" + #: builtin/index-pack.c #, c-format msgid "bad %s" @@ -10432,11 +10457,6 @@ msgstr "未知的策略选项:-X%s" msgid "malformed input line: '%s'." msgstr "格式错误的输入行:'%s'。" -#: builtin/merge-tree.c -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "合并无法继续;得到不干净的结果 %d" - #: builtin/merge.c msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<选项>] [<提交>...]" @@ -11454,6 +11474,15 @@ msgstr "git pack-objects [<选项>] <前缀名称> [< <引用列表> | < <对象 #: builtin/pack-objects.c #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "无效的 --name-hash-version 选项:%d" + +#: builtin/pack-objects.c +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "当前,--write-bitmap-index 要求 --name-hash-version=1" + +#: builtin/pack-objects.c +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -11857,7 +11886,11 @@ msgstr "协议" #: builtin/pack-objects.c msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" -msgstr "使用此协议排除任何已配置的 uploadpack.blobpackfileuri" +msgstr "排除掉采用该协议的 uploadpack.blobpackfileuri 配置项" + +#: builtin/pack-objects.c +msgid "use the specified name-hash function to group similar objects" +msgstr "使用指定的名称哈希函数对相似的对象进行分组" #: builtin/pack-objects.c #, c-format @@ -12284,8 +12317,8 @@ msgid "" "upstream, see 'push.autoSetupRemote' in 'git help config'.\n" msgstr "" "\n" -"为了让没有追踪上游的分支自动配置,参见 'git help config' 中的 push." -"autoSetupRemote。\n" +"为了让没有追踪上游的分支自动配置,参见 'git help config' 中的 " +"push.autoSetupRemote。\n" #: builtin/push.c #, c-format @@ -13294,8 +13327,8 @@ msgid "invalid ref format: %s" msgstr "无效的引用格式:%s" #: builtin/refs.c -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<格式> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<格式> [--no-reflog] [--dry-run]" #: builtin/refs.c msgid "git refs verify [--strict] [--verbose]" @@ -13310,6 +13343,10 @@ msgid "perform a non-destructive dry-run" msgstr "进行非破坏性的试运行(dry-run)" #: builtin/refs.c +msgid "drop reflogs entirely during the migration" +msgstr "在迁移期间丢弃引用日志" + +#: builtin/refs.c msgid "missing --ref-format=<format>" msgstr "缺少 --ref-format=<格式>" @@ -13881,8 +13918,14 @@ msgid "be verbose; must be placed before a subcommand" msgstr "冗长输出;必须置于子命令之前" #: builtin/repack.c -msgid "git repack [<options>]" -msgstr "git repack [<选项>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<包名>]\n" +"[--write-midx] [--name-hash-version=<n>]" #: builtin/repack.c msgid "" @@ -13975,6 +14018,11 @@ msgid "pass --no-reuse-object to git-pack-objects" msgstr "向 git-pack-objects 传递参数 --no-reuse-object" #: builtin/repack.c +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "指定要使用的名称哈希算法,以实现按照路径对相似对象分组" + +#: builtin/repack.c msgid "do not run git-update-server-info" msgstr "不运行 git-update-server-info" @@ -14039,10 +14087,6 @@ msgid "write a multi-pack index of the resulting packs" msgstr "写入结果包的多包索引" #: builtin/repack.c -msgid "pack prefix to store a pack containing pruned objects" -msgstr "储存被清除的对象的包的前缀" - -#: builtin/repack.c msgid "pack prefix to store a pack containing filtered out objects" msgstr "储存被过滤的对象的包的前缀" @@ -14315,10 +14359,6 @@ msgid "need some commits to replay" msgstr "需要一些提交来重放" #: builtin/replay.c -msgid "--onto and --advance are incompatible" -msgstr "--onto 和 --advance 不兼容" - -#: builtin/replay.c msgid "all positive revisions given must be references" msgstr "提供的所有正向版本必须为引用" @@ -17546,6 +17586,10 @@ msgid "Create an archive of files from a named tree" msgstr "基于一个指定的树创建文件存档" #: command-list.h +msgid "Download missing objects in a partial clone" +msgstr "下载部分克隆中缺失的对象" + +#: command-list.h msgid "Use binary search to find the commit that introduced a bug" msgstr "通过二分查找定位引入 bug 的提交" @@ -18927,8 +18971,8 @@ msgid "" "remote URLs cannot be configured in file directly or indirectly included by " "includeIf.hasconfig:remote.*.url" msgstr "" -"远程 URL 不能在文件中配置,不管直接地还是通过 includeIf.hasconfig:remote.*." -"url 间接地包含。" +"远程 URL 不能在文件中配置,不管直接地还是通过 " +"includeIf.hasconfig:remote.*.url 间接地包含。" #: config.c #, c-format @@ -19926,6 +19970,14 @@ msgid "invalid regex given to -I: '%s'" msgstr "选项 -I 的正则表达式无效:'%s'" #: diff.c +msgid "-G requires a non-empty argument" +msgstr "-G 需要一个非空参数" + +#: diff.c +msgid "-S requires a non-empty argument" +msgstr "-S 需要一个非空参数" + +#: diff.c #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "无法解析 --submodule 选项的参数:'%s'" @@ -22430,7 +22482,7 @@ msgstr "无法读取替代文件" #: object-file.c msgid "unable to move new alternates file into place" -msgstr "无法将新的替代文件移动到位" +msgstr "无法将新的备用文件移动到位" #: object-file.c #, c-format @@ -22553,6 +22605,11 @@ msgstr "无法写文件 %s" #: object-file.c #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "无法写入反复消失的文件 %s" + +#: object-file.c +#, c-format msgid "unable to set permission to '%s'" msgstr "无法为 '%s' 设置权限" @@ -23233,6 +23290,55 @@ msgstr "未知开关 `%c'" msgid "unknown non-ascii option in string: `%s'" msgstr "字符串中未知的非 ascii 字符选项:`%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid " <%s>" +msgstr " <%s>" + #: parse-options.c msgid "..." msgstr "..." @@ -23336,6 +23442,25 @@ msgstr "对于 '%2$s' 的错误的布尔环境取值 '%1$s'" msgid "failed to parse %s" msgstr "无法解析 %s" +#: path-walk.c +#, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "无法遍历树 %s 的子节点:未找到" + +#: path-walk.c +#, c-format +msgid "failed to find object %s" +msgstr "无法找到对象 %s" + +#: path-walk.c +#, c-format +msgid "failed to find tag %s" +msgstr "无法找到标签 %s" + +#: path-walk.c +msgid "failed to setup revision walk" +msgstr "无法设置版本遍历" + #: path.c #, c-format msgid "Could not make %s writable by group" @@ -23517,6 +23642,26 @@ msgstr "promisor 远程名称不能以 '/' 开始:%s" msgid "could not fetch %s from promisor remote" msgstr "无法从承诺者远程获取 %s" +#: promisor-remote.c +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "已知远程名称为 '%s',但 url 为 '%s' 而不是 '%s'" + +#: promisor-remote.c +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "配置项 '%2$s' 为未知的取值 '%1$s'" + +#: promisor-remote.c +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "远程信息中的未知元素 '%s'" + +#: promisor-remote.c +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "未找到已接受的承诺者远程 '%s'" + #: protocol-caps.c msgid "object-info: expected flush after arguments" msgstr "object-info:在参数之后应有一个 flush" @@ -24484,6 +24629,16 @@ msgstr "引用名 %s 是一个符号引用,不支持复制" msgid "invalid refspec '%s'" msgstr "无效的引用规格:'%s'" +#: refspec.c +#, c-format +msgid "pattern '%s' has no '*'" +msgstr "模式 '%s' 没有 '*'" + +#: refspec.c +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "替换 '%s' 没有 '*'" + #: remote-curl.c #, c-format msgid "invalid quoting in push-option value: '%s'" @@ -24637,6 +24792,28 @@ msgstr "remote-curl:未知的来自 git 的命令 '%s'" #: remote.c #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"正在从 \"%s/%s\" 读取远程内容,该内容被提名删除。\n" +"\n" +"如果你仍然在使用 \"remotes/\" 目录,建议迁移为基于配置远程的方式:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"如果你无法迁移,请发送电子邮件至 <git@vger.kernel.org> 告知我们你\n" +"仍然需要使用它的原因。" + +#: remote.c +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "配置的远程短名称不能以 '/' 开始:%s" @@ -24680,16 +24857,6 @@ msgstr "%s 同时跟踪 %s 和 %s" #: remote.c #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "模式的键 '%s' 没有 '*'" - -#: remote.c -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "模式的值 '%s' 没有 '*'" - -#: remote.c -#, c-format msgid "src refspec %s does not match any" msgstr "源引用规格 %s 没有匹配" @@ -26956,6 +27123,34 @@ msgstr "在每次迭代前清除缓存树" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "缓存树中无效化的条目数量(默认 0)" +#: t/helper/test-path-walk.c +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <选项> -- <版本选项>" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of blob objects" +msgstr "切换是否包含数据对象" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of commit objects" +msgstr "切换是否包含提交对象" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tag objects" +msgstr "切换是否包含标签对象" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tree objects" +msgstr "切换是否包含树对象" + +#: t/helper/test-path-walk.c +msgid "toggle pruning of uninteresting paths" +msgstr "切换对无趣路径的修剪" + +#: t/helper/test-path-walk.c +msgid "read a pattern list over stdin" +msgstr "从标准输入读取模式列表" + #: t/helper/test-reach.c #, c-format msgid "commit %s is not marked reachable" @@ -27703,6 +27898,11 @@ msgstr "错误:" msgid "warning: " msgstr "警告:" +#: version.c +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() 失败,错误为 '%s'(%d)\n" + #: walker.c msgid "Fetching objects" msgstr "正在获取对象" diff --git a/po/zh_TW.po b/po/zh_TW.po index a61f544304..aa74d6537a 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -30,8 +30,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-12-28 13:16+0800\n" -"PO-Revision-Date: 2024-12-28 13:23+0800\n" +"POT-Creation-Date: 2025-03-09 10:39+0800\n" +"PO-Revision-Date: 2025-03-09 10:52+0800\n" "Last-Translator: Yi-Jyun Pan <pan93412@gmail.com>\n" "Language-Team: Chinese (Traditional) <http://weblate.slat.org/projects/git-" "po/git-cli/zh_Hant/>\n" @@ -2841,6 +2841,22 @@ msgstr "git archive:通訊協定錯誤" msgid "git archive: expected a flush" msgstr "git archive:預期收到 flush 封包" +#: builtin/backfill.c +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [--[no-]sparse]" + +#: builtin/backfill.c +msgid "problem loading sparse-checkout" +msgstr "載入稀疏簽出時發生問題" + +#: builtin/backfill.c +msgid "Minimum number of objects to request at a time" +msgstr "一次請求的最小物件數量" + +#: builtin/backfill.c +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "將缺少的物件限制於目前的稀疏簽出" + #: builtin/bisect.c msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" @@ -2872,22 +2888,22 @@ msgstr "git bisect run <cmd> [<arg>...]" #: builtin/bisect.c #, c-format msgid "cannot open file '%s' in mode '%s'" -msgstr "無法以「%2$s」模式開啟「%1$s」檔案" +msgstr "無法以「%2$s」模式開啟檔案「%1$s」" #: builtin/bisect.c #, c-format msgid "could not write to file '%s'" -msgstr "無法寫入「%s」檔案" +msgstr "無法寫入檔案「%s」" #: builtin/bisect.c #, c-format msgid "cannot open file '%s' for reading" -msgstr "無法開啟「%s」檔案進行讀取" +msgstr "無法開啟檔案「%s」來讀取" #: builtin/bisect.c #, c-format msgid "'%s' is not a valid term" -msgstr "「%s」不是有效術語" +msgstr "「%s」不是有效的術語" #: builtin/bisect.c #, c-format @@ -2917,7 +2933,7 @@ msgstr "「%s」不是有效的提交" #, c-format msgid "" "could not check out original HEAD '%s'. Try 'git bisect reset <commit>'." -msgstr "無法簽出原始 HEAD「%s」。請嘗試「git bisect reset <commit>」。" +msgstr "無法簽出原本的 HEAD「%s」。請嘗試「git bisect reset <commit>」。" #: builtin/bisect.c #, c-format @@ -2937,7 +2953,7 @@ msgstr "無法開啟檔案「%s」" #: builtin/bisect.c #, c-format msgid "Invalid command: you're currently in a %s/%s bisect" -msgstr "命令無效:您目前正處於二分搜尋 %s/%s 的狀態" +msgstr "命令無效:您正處於二分搜尋 %s/%s 的狀態" #: builtin/bisect.c #, c-format @@ -3263,7 +3279,7 @@ msgstr "顯示作者信箱而非名稱(預設值:off)" msgid "ignore whitespace differences" msgstr "忽略空白差異" -#: builtin/blame.c builtin/log.c +#: builtin/blame.c builtin/clone.c builtin/log.c msgid "rev" msgstr "rev" @@ -3776,11 +3792,6 @@ msgid "git version:\n" msgstr "git 版本:\n" #: builtin/bugreport.c -#, c-format -msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() 失敗,錯誤:「%s」(%d)\n" - -#: builtin/bugreport.c msgid "compiler info: " msgstr "編譯器資訊: " @@ -5010,8 +5021,112 @@ msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "clean.requireForce 是 true 且未給定 -f 選項:拒絕清理" #: builtin/clone.c -msgid "git clone [<options>] [--] <repo> [<dir>]" -msgstr "git clone [<options>] [--] <repo> [<dir>]" +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: 不能為「%s」新增一個備用:%s\n" + +#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c +#, c-format +msgid "failed to stat '%s'" +msgstr "對「%s」呼叫 stat 失敗" + +#: builtin/clone.c +#, c-format +msgid "%s exists and is not a directory" +msgstr "%s 存在且不是目錄" + +#: builtin/clone.c +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "「%s」是符號連結,故不能使用 --local 複製" + +#: builtin/clone.c +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "無法在「%s」上啟動迭代器" + +#: builtin/clone.c +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "符號連結「%s」已存在,拒絕使用 --local 複製" + +#: builtin/clone.c compat/precompose_utf8.c +#, c-format +msgid "failed to unlink '%s'" +msgstr "無法刪除「%s」" + +#: builtin/clone.c +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "無法檢查位於「%s」的硬連結" + +#: builtin/clone.c +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "硬連結與位於「%s」的來源不同" + +#: builtin/clone.c +#, c-format +msgid "failed to create link '%s'" +msgstr "建立連結「%s」失敗" + +#: builtin/clone.c +#, c-format +msgid "failed to copy file to '%s'" +msgstr "複製檔案至「%s」失敗" + +#: builtin/clone.c refs/files-backend.c +#, c-format +msgid "failed to iterate over '%s'" +msgstr "無法在「%s」上迭代" + +#: builtin/clone.c +#, c-format +msgid "done.\n" +msgstr "完成。\n" + +#: builtin/clone.c +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"複製成功,但是簽出失敗。\n" +"您可以透過「git status」檢查哪些已被簽出,然後使用指令\n" +"「git restore --source=HEAD :/」重試\n" + +#: builtin/clone.c fetch-pack.c +msgid "remote did not send all necessary objects" +msgstr "遠端沒有傳送所有必需的物件" + +#: builtin/clone.c +#, c-format +msgid "unable to update %s" +msgstr "不能更新 %s" + +#: builtin/clone.c +msgid "failed to initialize sparse-checkout" +msgstr "無法初始化稀疏簽出" + +#: builtin/clone.c +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "遠端 HEAD 指向不存在的引用,無法簽出" + +#: builtin/clone.c +msgid "unable to checkout working tree" +msgstr "不能簽出工作區" + +#: builtin/clone.c +msgid "unable to write parameters to config file" +msgstr "無法將參數寫入組態檔案" + +#: builtin/clone.c +msgid "cannot repack to clean up" +msgstr "無法執行 repack 來清理" + +#: builtin/clone.c +msgid "cannot unlink temporary alternates file" +msgstr "無法刪除暫存 alternates 檔案" #: builtin/clone.c msgid "don't clone shallow repository" @@ -5084,6 +5199,10 @@ msgid "checkout <branch> instead of the remote's HEAD" msgstr "簽出 <branch> 而不是遠端 HEAD" #: builtin/clone.c +msgid "clone single revision <rev> and check out" +msgstr "複製單個修訂版 <rev> 並簽出" + +#: builtin/clone.c msgid "path to git-upload-pack on the remote" msgstr "遠端 git-upload-pack 路徑" @@ -5112,8 +5231,8 @@ msgid "clone only one branch, HEAD or --branch" msgstr "只複製一個分支、HEAD 或 --branch" #: builtin/clone.c -msgid "don't clone any tags, and make later fetches not to follow them" -msgstr "不要複製任何標籤,之後取得也不要追蹤這些標籤" +msgid "clone tags, and make later fetches not to follow them" +msgstr "複製標籤,並使後續抓取不要追蹤這些標籤" #: builtin/clone.c msgid "any cloned submodules will be shallow" @@ -5170,117 +5289,8 @@ msgid "a URI for downloading bundles before fetching from origin remote" msgstr "在從 origin 遠端抓取前,用來下載套件包的 URI" #: builtin/clone.c -#, c-format -msgid "info: Could not add alternate for '%s': %s\n" -msgstr "info: 不能為 '%s' 新增一個備用:%s\n" - -#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c -#, c-format -msgid "failed to stat '%s'" -msgstr "對 '%s' 呼叫 stat 失敗" - -#: builtin/clone.c -#, c-format -msgid "%s exists and is not a directory" -msgstr "%s 存在且不是一個目錄" - -#: builtin/clone.c -#, c-format -msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "「%s」是個符號連結,故不能使用 --local 複製" - -#: builtin/clone.c -#, c-format -msgid "failed to start iterator over '%s'" -msgstr "無法在 '%s' 上啟動疊代器" - -#: builtin/clone.c -#, c-format -msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "「%s」符號連結已存在,拒絕使用 --local 複製" - -#: builtin/clone.c compat/precompose_utf8.c -#, c-format -msgid "failed to unlink '%s'" -msgstr "無法刪除「%s」" - -#: builtin/clone.c -#, c-format -msgid "hardlink cannot be checked at '%s'" -msgstr "無法檢查位於「%s」的硬連結" - -#: builtin/clone.c -#, c-format -msgid "hardlink different from source at '%s'" -msgstr "硬連結與位於 '%s' 的來源不同" - -#: builtin/clone.c -#, c-format -msgid "failed to create link '%s'" -msgstr "建立連結 '%s' 失敗" - -#: builtin/clone.c -#, c-format -msgid "failed to copy file to '%s'" -msgstr "複製檔案至 '%s' 失敗" - -#: builtin/clone.c refs/files-backend.c -#, c-format -msgid "failed to iterate over '%s'" -msgstr "無法在 '%s' 上疊代" - -#: builtin/clone.c -#, c-format -msgid "done.\n" -msgstr "完成。\n" - -#: builtin/clone.c -msgid "" -"Clone succeeded, but checkout failed.\n" -"You can inspect what was checked out with 'git status'\n" -"and retry with 'git restore --source=HEAD :/'\n" -msgstr "" -"複製成功,但是簽出失敗。\n" -"您可以透過 'git status' 檢查哪些已被簽出,然後使用指令\n" -"'git restore --source=HEAD :/' 重試\n" - -#: builtin/clone.c -#, c-format -msgid "Could not find remote branch %s to clone." -msgstr "找不到要複製的遠端分支 %s。" - -#: builtin/clone.c fetch-pack.c -msgid "remote did not send all necessary objects" -msgstr "遠端沒有傳送所有必需的物件" - -#: builtin/clone.c -#, c-format -msgid "unable to update %s" -msgstr "不能更新 %s" - -#: builtin/clone.c -msgid "failed to initialize sparse-checkout" -msgstr "無法初始化稀疏簽出" - -#: builtin/clone.c -msgid "remote HEAD refers to nonexistent ref, unable to checkout" -msgstr "遠端 HEAD 指向一個不存在的引用,無法簽出" - -#: builtin/clone.c -msgid "unable to checkout working tree" -msgstr "不能簽出工作區" - -#: builtin/clone.c -msgid "unable to write parameters to config file" -msgstr "無法將參數寫入設定檔案" - -#: builtin/clone.c -msgid "cannot repack to clean up" -msgstr "無法執行 repack 來清理" - -#: builtin/clone.c -msgid "cannot unlink temporary alternates file" -msgstr "無法刪除暫存 alternates 檔案" +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<options>] [--] <repo> [<dir>]" #: builtin/clone.c msgid "Too many arguments." @@ -5404,7 +5414,12 @@ msgstr "遠端傳輸回報錯誤" #: builtin/clone.c #, c-format msgid "Remote branch %s not found in upstream %s" -msgstr "遠端分支 %s 在上游 %s 未發現" +msgstr "上游 %2$s 上找不到遠端分支 %1$s" + +#: builtin/clone.c +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "上游 %2$s 上找不到遠端修訂版 %1$s" #: builtin/clone.c msgid "You appear to have cloned an empty repository." @@ -5469,7 +5484,8 @@ msgstr "" "[no-]progress]\n" " <split-options>" -#: builtin/commit-graph.c builtin/fetch.c builtin/log.c builtin/repack.c +#: builtin/commit-graph.c builtin/fetch.c builtin/gc.c builtin/log.c +#: builtin/repack.c msgid "dir" msgstr "目錄" @@ -5626,8 +5642,19 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree:讀取失敗" #: builtin/commit.c -msgid "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +#| msgid "" +#| "git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +#| " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" +#| "reword):]<commit>]\n" +#| " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" +#| " [--allow-empty-message] [--no-verify] [-e] [--" +#| "author=<author>]\n" +#| " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" +#| " [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n" +#| " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" +#| " [--] [<pathspec>...]" +msgid "" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -5637,7 +5664,7 @@ msgid "" " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" " [--] [<pathspec>...]" msgstr "" -"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" "reword):]<commit>]\n" " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" @@ -7358,14 +7385,14 @@ msgid "" "Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" "if you do not want to see this message. Specifically running\n" -"'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" -"until the remote changes HEAD to something else." +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." msgstr "" -"執行「git remote set-head %s %s」以追蹤這個變更,或者\n" -"如果您不想看到這則訊息,請將「remote.%s.followRemoteHEAD」\n" -"組態選項設定成不同的值。更具體些來說,執行\n" -"「git config set remote.%s.followRemoteHEAD %s」會停用這個警告,\n" -"直到遠端將 HEAD 變更為其他內容。" +"執行「git remote set-head %s %s」來跟進此差異,或者\n" +"如果您不想看到這則訊息,請將「remote.%s.followRemoteHEAD」組態選項\n" +"設定成別的值。更具體些來說,執行\n" +"「git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s」\n" +"會停用這個警告,直到遠端將 HEAD 改為指向其他東西。" #: builtin/fetch.c msgid "multiple branches detected, incompatible with --set-upstream" @@ -8216,6 +8243,10 @@ msgstr "強制執行 gc 即使另外一個 gc 正在執行" msgid "repack all other packs except the largest pack" msgstr "除了最大的包之外,對所有其它包重新打包" +#: builtin/gc.c builtin/repack.c +msgid "pack prefix to store a pack containing pruned objects" +msgstr "將前綴打包並儲存為包含已剪除物件的包" + #: builtin/gc.c #, c-format msgid "failed to parse gc.logExpiry value %s" @@ -9209,6 +9240,11 @@ msgstr "無法結束 pack-objects 來重新封包" msgid "Cannot come back to cwd" msgstr "無法返回目前工作目錄" +#: builtin/index-pack.c builtin/unpack-objects.c +#, c-format +msgid "bad --pack_header: %s" +msgstr "無效的 --pack_header:%s" + #: builtin/index-pack.c #, c-format msgid "bad %s" @@ -10311,11 +10347,6 @@ msgstr "未知的策略選項:-X%s" msgid "malformed input line: '%s'." msgstr "格式錯誤的輸入行:'%s'。" -#: builtin/merge-tree.c -#, c-format -msgid "merging cannot continue; got unclean result of %d" -msgstr "無法繼續合併:從 %d 收到的結果不乾淨" - #: builtin/merge.c msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<選項>] [<提交>...]" @@ -11334,6 +11365,15 @@ msgstr "git pack-objects [<選項>] <前綴名稱> [< <引用列表> | < <物件 #: builtin/pack-objects.c #, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "無效的 --name-hash-version 選項:%d" + +#: builtin/pack-objects.c +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "目前 --write-bitmap-index 需要指定 --name-hash-version=1" + +#: builtin/pack-objects.c +#, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " "pack %s" @@ -11468,8 +11508,8 @@ msgid "" "value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-" "hash> <uri>' (got '%s')" msgstr "" -"uploadpack.blobpackfileuri 的值格式必須為 '<object-hash> <pack-hash> " -"<uri>' (收到 '%s')" +"uploadpack.blobpackfileuri 的值格式必須為「<object-hash> <pack-hash> <uri>」" +"(收到「%s」)" #: builtin/pack-objects.c #, c-format @@ -11740,6 +11780,10 @@ msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "排除任何設定過,使用此通訊協定的 uploadpack.blobpackfileuri" #: builtin/pack-objects.c +msgid "use the specified name-hash function to group similar objects" +msgstr "使用指定的名稱雜湊函式來為相似物件分組" + +#: builtin/pack-objects.c #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "增量鏈深度 %d 太深了,強制為 %d" @@ -13178,8 +13222,9 @@ msgid "invalid ref format: %s" msgstr "無效的引用格式:%s" #: builtin/refs.c -msgid "git refs migrate --ref-format=<format> [--dry-run]" -msgstr "git refs migrate --ref-format=<格式> [--dry-run]" +#| msgid "git refs migrate --ref-format=<format> [--dry-run]" +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" #: builtin/refs.c msgid "git refs verify [--strict] [--verbose]" @@ -13194,6 +13239,10 @@ msgid "perform a non-destructive dry-run" msgstr "進行非破壞性的試執行" #: builtin/refs.c +msgid "drop reflogs entirely during the migration" +msgstr "在遷移過程中完全拋棄 reflog" + +#: builtin/refs.c msgid "missing --ref-format=<format>" msgstr "缺少 --ref-format=<格式>" @@ -13764,8 +13813,14 @@ msgid "be verbose; must be placed before a subcommand" msgstr "詳細輸出;必須置於子指令之前" #: builtin/repack.c -msgid "git repack [<options>]" -msgstr "git repack [<選項>]" +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" #: builtin/repack.c msgid "" @@ -13858,6 +13913,11 @@ msgid "pass --no-reuse-object to git-pack-objects" msgstr "向 git-pack-objects 傳遞參數 --no-reuse-object" #: builtin/repack.c +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "指定要用來以路徑為相似物件分組的名稱雜湊版本" + +#: builtin/repack.c msgid "do not run git-update-server-info" msgstr "不執行 git-update-server-info" @@ -13922,10 +13982,6 @@ msgid "write a multi-pack index of the resulting packs" msgstr "寫入結果包的多包索引" #: builtin/repack.c -msgid "pack prefix to store a pack containing pruned objects" -msgstr "封裝前綴,儲存為包含過時物件的套件包" - -#: builtin/repack.c msgid "pack prefix to store a pack containing filtered out objects" msgstr "將前綴進行包裝,儲存為包含已過濾物件的封裝" @@ -14198,10 +14254,6 @@ msgid "need some commits to replay" msgstr "需要一些提交才能重放" #: builtin/replay.c -msgid "--onto and --advance are incompatible" -msgstr "--onto 和 --advance 不相容" - -#: builtin/replay.c msgid "all positive revisions given must be references" msgstr "提供的所有正向修訂集必須為引用" @@ -17424,6 +17476,10 @@ msgid "Create an archive of files from a named tree" msgstr "基於命名過的樹建立檔案封存" #: command-list.h +msgid "Download missing objects in a partial clone" +msgstr "在部分複製中下載缺少的物件" + +#: command-list.h msgid "Use binary search to find the commit that introduced a bug" msgstr "透過二分搜尋定位引入 bug 的提交" @@ -18378,8 +18434,8 @@ msgstr "嘗試寫入提交圖,但「core.commitGraph」已停用" #: commit-graph.c #, c-format msgid "" -"attempting to write a commit-graph, but 'commitGraph." -"changedPathsVersion' (%d) is not supported" +"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " +"(%d) is not supported" msgstr "嘗試寫入提交圖,但不支援「commitGraph.changedPathsVersion」(%d)" #: commit-graph.c @@ -19791,6 +19847,14 @@ msgid "invalid regex given to -I: '%s'" msgstr "傳入 -I 的常規表示式無效:「%s」" #: diff.c +msgid "-G requires a non-empty argument" +msgstr "-G 需要非空白引數" + +#: diff.c +msgid "-S requires a non-empty argument" +msgstr "-S 需要非空白引數" + +#: diff.c #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "無法解析 --submodule 選項的參數:'%s'" @@ -22419,6 +22483,11 @@ msgstr "無法寫檔案 %s" #: object-file.c #, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "無法寫入重複消失的檔案 %s" + +#: object-file.c +#, c-format msgid "unable to set permission to '%s'" msgstr "無法為 '%s' 設定權限" @@ -23100,6 +23169,55 @@ msgstr "未知開關 `%c'" msgid "unknown non-ascii option in string: `%s'" msgstr "字串中未知的非 ascii 字元選項:`%s'" +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid " <%s>" +msgstr " <%s>" + #: parse-options.c msgid "..." msgstr "..." @@ -23203,6 +23321,25 @@ msgstr "「%2$s」的「%1$s」布林環境值無效" msgid "failed to parse %s" msgstr "解析 %s 失敗" +#: path-walk.c +#, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "無法走訪樹 %s 的子代:找不到" + +#: path-walk.c +#, c-format +msgid "failed to find object %s" +msgstr "找不到物件 %s" + +#: path-walk.c +#, c-format +msgid "failed to find tag %s" +msgstr "找不到標籤 %s" + +#: path-walk.c +msgid "failed to setup revision walk" +msgstr "無法設置修訂版走訪" + #: path.c #, c-format msgid "Could not make %s writable by group" @@ -23384,6 +23521,26 @@ msgstr "promisor 遠端名稱不能以 '/' 開始:%s" msgid "could not fetch %s from promisor remote" msgstr "無法從承諾者遠端抓取 %s" +#: promisor-remote.c +#, c-format +msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgstr "已知有遠端名為「%s」,但其 URL 為「%s」而非「%s」" + +#: promisor-remote.c +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "「%2$s」組態選項的值「%1$s」未知" + +#: promisor-remote.c +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "遠端資訊的元素「%s」未知" + +#: promisor-remote.c +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "找不到接受的承諾者遠端「%s」" + #: protocol-caps.c msgid "object-info: expected flush after arguments" msgstr "object-info:引數後預期要有 flush" @@ -24351,6 +24508,16 @@ msgstr "引用名稱 %s 是符號引用,不支援複製" msgid "invalid refspec '%s'" msgstr "無效的引用規格:「%s」" +#: refspec.c +#, c-format +msgid "pattern '%s' has no '*'" +msgstr "符合模式「%s」中沒有「*」" + +#: refspec.c +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "取代文字「%s」中沒有「*」" + #: remote-curl.c #, c-format msgid "invalid quoting in push-option value: '%s'" @@ -24504,6 +24671,28 @@ msgstr "remote-curl:未知的來自 git 的指令 '%s'" #: remote.c #, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"正在自「%s/%s」讀取遠端,該路徑已被標記為即將移除。\n" +"\n" +"如果您仍在使用「remotes/」目錄,建議您遷移至基於組態的遠端:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"如果您無法遷移,請告訴我們您為何仍需使用此功能,\n" +"請寄信至 <git@vger.kernel.org>。" + +#: remote.c +#, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "設定的遠端短名稱不能以 '/' 開始:%s" @@ -24547,16 +24736,6 @@ msgstr "%s 同時追蹤 %s 和 %s" #: remote.c #, c-format -msgid "key '%s' of pattern had no '*'" -msgstr "模式的鍵 '%s' 沒有 '*'" - -#: remote.c -#, c-format -msgid "value '%s' of pattern has no '*'" -msgstr "模式的值 '%s' 沒有 '*'" - -#: remote.c -#, c-format msgid "src refspec %s does not match any" msgstr "來源引用規格 %s 沒有符合項目" @@ -26824,6 +27003,34 @@ msgstr "每次迭代前清除快取樹狀物件" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "在快取樹狀物件中,要使失效的項目數量(預設值為 0)" +#: t/helper/test-path-walk.c +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <options> -- <revision-options>" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of blob objects" +msgstr "切換是否包含資料物件" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of commit objects" +msgstr "切換是否包含提交物件" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tag objects" +msgstr "切換是否包含標籤物件" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tree objects" +msgstr "切換是否包含樹狀物件" + +#: t/helper/test-path-walk.c +msgid "toggle pruning of uninteresting paths" +msgstr "切換是否剪除不重要路徑" + +#: t/helper/test-path-walk.c +msgid "read a pattern list over stdin" +msgstr "從標準輸入讀取模式清單" + #: t/helper/test-reach.c #, c-format msgid "commit %s is not marked reachable" @@ -27571,6 +27778,11 @@ msgstr "錯誤: " msgid "warning: " msgstr "警告: " +#: version.c +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "uname() 失敗,錯誤:「%s」(%d)\n" + #: walker.c msgid "Fetching objects" msgstr "正在抓取物件" @@ -28758,6 +28970,24 @@ msgid "Do you really want to send %s? [y|N]: " msgstr "您真的要傳送 %s?[y|N]: " #, c-format +#~ msgid "Could not find remote branch %s to clone." +#~ msgstr "找不到要複製的遠端分支 %s。" + +#, c-format +#~ msgid "merging cannot continue; got unclean result of %d" +#~ msgstr "無法繼續合併:從 %d 收到的結果不乾淨" + +#~ msgid "git repack [<options>]" +#~ msgstr "git repack [<選項>]" + +#~ msgid "--onto and --advance are incompatible" +#~ msgstr "--onto 和 --advance 不相容" + +#, c-format +#~ msgid "key '%s' of pattern had no '*'" +#~ msgstr "模式的鍵 '%s' 沒有 '*'" + +#, c-format #~ msgid "preferred pack (%s) is invalid" #~ msgstr "偏好的封包 (%s) 無效" diff --git a/preload-index.c b/preload-index.c index ab94d6f399..40ab2abafb 100644 --- a/preload-index.c +++ b/preload-index.c @@ -132,7 +132,9 @@ void preload_index(struct index_state *index, memset(&pd, 0, sizeof(pd)); if (refresh_flags & REFRESH_PROGRESS && isatty(2)) { - pd.progress = start_delayed_progress(_("Refreshing index"), index->cache_nr); + pd.progress = start_delayed_progress(the_repository, + _("Refreshing index"), + index->cache_nr); pthread_mutex_init(&pd.mutex, NULL); } diff --git a/prio-queue.h b/prio-queue.h index 36f370625f..38d032636d 100644 --- a/prio-queue.h +++ b/prio-queue.h @@ -22,13 +22,13 @@ typedef int (*prio_queue_compare_fn)(const void *one, const void *two, void *cb_data); struct prio_queue_entry { - unsigned ctr; + size_t ctr; void *data; }; struct prio_queue { prio_queue_compare_fn compare; - unsigned insertion_ctr; + size_t insertion_ctr; void *cb_data; size_t alloc, nr; struct prio_queue_entry *array; diff --git a/progress.c b/progress.c index a8fdfceb5c..8d5ae70f3a 100644 --- a/progress.c +++ b/progress.c @@ -9,7 +9,6 @@ */ #define GIT_TEST_PROGRESS_ONLY -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -37,6 +36,7 @@ struct throughput { }; struct progress { + struct repository *repo; const char *title; uint64_t last_value; uint64_t total; @@ -254,10 +254,12 @@ void display_progress(struct progress *progress, uint64_t n) display(progress, n, NULL); } -static struct progress *start_progress_delay(const char *title, uint64_t total, +static struct progress *start_progress_delay(struct repository *r, + const char *title, uint64_t total, unsigned delay, unsigned sparse) { struct progress *progress = xmalloc(sizeof(*progress)); + progress->repo = r; progress->title = title; progress->total = total; progress->last_value = -1; @@ -270,7 +272,7 @@ static struct progress *start_progress_delay(const char *title, uint64_t total, progress->title_len = utf8_strwidth(title); progress->split = 0; set_progress_signal(); - trace2_region_enter("progress", title, the_repository); + trace2_region_enter("progress", title, r); return progress; } @@ -284,14 +286,16 @@ static int get_default_delay(void) return delay_in_secs; } -struct progress *start_delayed_progress(const char *title, uint64_t total) +struct progress *start_delayed_progress(struct repository *r, + const char *title, uint64_t total) { - return start_progress_delay(title, total, get_default_delay(), 0); + return start_progress_delay(r, title, total, get_default_delay(), 0); } -struct progress *start_progress(const char *title, uint64_t total) +struct progress *start_progress(struct repository *r, + const char *title, uint64_t total) { - return start_progress_delay(title, total, 0, 0); + return start_progress_delay(r, title, total, 0, 0); } /* @@ -303,15 +307,17 @@ struct progress *start_progress(const char *title, uint64_t total) * When "sparse" is set, stop_progress() will automatically force the done * message to show 100%. */ -struct progress *start_sparse_progress(const char *title, uint64_t total) +struct progress *start_sparse_progress(struct repository *r, + const char *title, uint64_t total) { - return start_progress_delay(title, total, 0, 1); + return start_progress_delay(r, title, total, 0, 1); } -struct progress *start_delayed_sparse_progress(const char *title, +struct progress *start_delayed_sparse_progress(struct repository *r, + const char *title, uint64_t total) { - return start_progress_delay(title, total, get_default_delay(), 1); + return start_progress_delay(r, title, total, get_default_delay(), 1); } static void finish_if_sparse(struct progress *progress) @@ -341,14 +347,14 @@ static void force_last_update(struct progress *progress, const char *msg) static void log_trace2(struct progress *progress) { - trace2_data_intmax("progress", the_repository, "total_objects", + trace2_data_intmax("progress", progress->repo, "total_objects", progress->total); if (progress->throughput) - trace2_data_intmax("progress", the_repository, "total_bytes", + trace2_data_intmax("progress", progress->repo, "total_bytes", progress->throughput->curr_total); - trace2_region_leave("progress", progress->title, the_repository); + trace2_region_leave("progress", progress->title, progress->repo); } void stop_progress_msg(struct progress **p_progress, const char *msg) diff --git a/progress.h b/progress.h index 3a945637c8..ed068c7bab 100644 --- a/progress.h +++ b/progress.h @@ -3,6 +3,7 @@ #include "gettext.h" struct progress; +struct repository; #ifdef GIT_TEST_PROGRESS_ONLY @@ -14,10 +15,14 @@ void progress_test_force_update(void); void display_throughput(struct progress *progress, uint64_t total); void display_progress(struct progress *progress, uint64_t n); -struct progress *start_progress(const char *title, uint64_t total); -struct progress *start_sparse_progress(const char *title, uint64_t total); -struct progress *start_delayed_progress(const char *title, uint64_t total); -struct progress *start_delayed_sparse_progress(const char *title, +struct progress *start_progress(struct repository *r, + const char *title, uint64_t total); +struct progress *start_sparse_progress(struct repository *r, + const char *title, uint64_t total); +struct progress *start_delayed_progress(struct repository *r, + const char *title, uint64_t total); +struct progress *start_delayed_sparse_progress(struct repository *r, + const char *title, uint64_t total); void stop_progress_msg(struct progress **p_progress, const char *msg); static inline void stop_progress(struct progress **p_progress) diff --git a/promisor-remote.c b/promisor-remote.c index c714f4f007..6a0a61382f 100644 --- a/promisor-remote.c +++ b/promisor-remote.c @@ -11,6 +11,8 @@ #include "strvec.h" #include "packfile.h" #include "environment.h" +#include "url.h" +#include "version.h" struct promisor_remote_config { struct promisor_remote *promisors; @@ -221,6 +223,18 @@ int repo_has_promisor_remote(struct repository *r) return !!repo_promisor_remote_find(r, NULL); } +int repo_has_accepted_promisor_remote(struct repository *r) +{ + struct promisor_remote *p; + + promisor_remote_init(r); + + for (p = r->promisor_remote_config->promisors; p; p = p->next) + if (p->accepted) + return 1; + return 0; +} + static int remove_fetched_oids(struct repository *repo, struct object_id **oids, int oid_nr, int to_free) @@ -292,3 +306,231 @@ all_fetched: if (to_free) free(remaining_oids); } + +static int allow_unsanitized(char ch) +{ + if (ch == ',' || ch == ';' || ch == '%') + return 0; + return ch > 32 && ch < 127; +} + +static void promisor_info_vecs(struct repository *repo, + struct strvec *names, + struct strvec *urls) +{ + struct promisor_remote *r; + + promisor_remote_init(repo); + + for (r = repo->promisor_remote_config->promisors; r; r = r->next) { + char *url; + char *url_key = xstrfmt("remote.%s.url", r->name); + + strvec_push(names, r->name); + strvec_push(urls, git_config_get_string(url_key, &url) ? NULL : url); + + free(url); + free(url_key); + } +} + +char *promisor_remote_info(struct repository *repo) +{ + struct strbuf sb = STRBUF_INIT; + int advertise_promisors = 0; + struct strvec names = STRVEC_INIT; + struct strvec urls = STRVEC_INIT; + + git_config_get_bool("promisor.advertise", &advertise_promisors); + + if (!advertise_promisors) + return NULL; + + promisor_info_vecs(repo, &names, &urls); + + if (!names.nr) + return NULL; + + for (size_t i = 0; i < names.nr; i++) { + if (i) + strbuf_addch(&sb, ';'); + strbuf_addstr(&sb, "name="); + strbuf_addstr_urlencode(&sb, names.v[i], allow_unsanitized); + if (urls.v[i]) { + strbuf_addstr(&sb, ",url="); + strbuf_addstr_urlencode(&sb, urls.v[i], allow_unsanitized); + } + } + + strvec_clear(&names); + strvec_clear(&urls); + + return strbuf_detach(&sb, NULL); +} + +/* + * Find first index of 'nicks' where there is 'nick'. 'nick' is + * compared case insensitively to the strings in 'nicks'. If not found + * 'nicks->nr' is returned. + */ +static size_t remote_nick_find(struct strvec *nicks, const char *nick) +{ + for (size_t i = 0; i < nicks->nr; i++) + if (!strcasecmp(nicks->v[i], nick)) + return i; + return nicks->nr; +} + +enum accept_promisor { + ACCEPT_NONE = 0, + ACCEPT_KNOWN_URL, + ACCEPT_KNOWN_NAME, + ACCEPT_ALL +}; + +static int should_accept_remote(enum accept_promisor accept, + const char *remote_name, const char *remote_url, + struct strvec *names, struct strvec *urls) +{ + size_t i; + + if (accept == ACCEPT_ALL) + return 1; + + i = remote_nick_find(names, remote_name); + + if (i >= names->nr) + /* We don't know about that remote */ + return 0; + + if (accept == ACCEPT_KNOWN_NAME) + return 1; + + if (accept != ACCEPT_KNOWN_URL) + BUG("Unhandled 'enum accept_promisor' value '%d'", accept); + + if (!strcmp(urls->v[i], remote_url)) + return 1; + + warning(_("known remote named '%s' but with url '%s' instead of '%s'"), + remote_name, urls->v[i], remote_url); + + return 0; +} + +static void filter_promisor_remote(struct repository *repo, + struct strvec *accepted, + const char *info) +{ + struct strbuf **remotes; + const char *accept_str; + enum accept_promisor accept = ACCEPT_NONE; + struct strvec names = STRVEC_INIT; + struct strvec urls = STRVEC_INIT; + + if (!git_config_get_string_tmp("promisor.acceptfromserver", &accept_str)) { + if (!*accept_str || !strcasecmp("None", accept_str)) + accept = ACCEPT_NONE; + else if (!strcasecmp("KnownUrl", accept_str)) + accept = ACCEPT_KNOWN_URL; + else if (!strcasecmp("KnownName", accept_str)) + accept = ACCEPT_KNOWN_NAME; + else if (!strcasecmp("All", accept_str)) + accept = ACCEPT_ALL; + else + warning(_("unknown '%s' value for '%s' config option"), + accept_str, "promisor.acceptfromserver"); + } + + if (accept == ACCEPT_NONE) + return; + + if (accept != ACCEPT_ALL) + promisor_info_vecs(repo, &names, &urls); + + /* Parse remote info received */ + + remotes = strbuf_split_str(info, ';', 0); + + for (size_t i = 0; remotes[i]; i++) { + struct strbuf **elems; + const char *remote_name = NULL; + const char *remote_url = NULL; + char *decoded_name = NULL; + char *decoded_url = NULL; + + strbuf_strip_suffix(remotes[i], ";"); + elems = strbuf_split(remotes[i], ','); + + for (size_t j = 0; elems[j]; j++) { + int res; + strbuf_strip_suffix(elems[j], ","); + res = skip_prefix(elems[j]->buf, "name=", &remote_name) || + skip_prefix(elems[j]->buf, "url=", &remote_url); + if (!res) + warning(_("unknown element '%s' from remote info"), + elems[j]->buf); + } + + if (remote_name) + decoded_name = url_percent_decode(remote_name); + if (remote_url) + decoded_url = url_percent_decode(remote_url); + + if (decoded_name && should_accept_remote(accept, decoded_name, decoded_url, &names, &urls)) + strvec_push(accepted, decoded_name); + + strbuf_list_free(elems); + free(decoded_name); + free(decoded_url); + } + + strvec_clear(&names); + strvec_clear(&urls); + strbuf_list_free(remotes); +} + +char *promisor_remote_reply(const char *info) +{ + struct strvec accepted = STRVEC_INIT; + struct strbuf reply = STRBUF_INIT; + + filter_promisor_remote(the_repository, &accepted, info); + + if (!accepted.nr) + return NULL; + + for (size_t i = 0; i < accepted.nr; i++) { + if (i) + strbuf_addch(&reply, ';'); + strbuf_addstr_urlencode(&reply, accepted.v[i], allow_unsanitized); + } + + strvec_clear(&accepted); + + return strbuf_detach(&reply, NULL); +} + +void mark_promisor_remotes_as_accepted(struct repository *r, const char *remotes) +{ + struct strbuf **accepted_remotes = strbuf_split_str(remotes, ';', 0); + + for (size_t i = 0; accepted_remotes[i]; i++) { + struct promisor_remote *p; + char *decoded_remote; + + strbuf_strip_suffix(accepted_remotes[i], ";"); + decoded_remote = url_percent_decode(accepted_remotes[i]->buf); + + p = repo_promisor_remote_find(r, decoded_remote); + if (p) + p->accepted = 1; + else + warning(_("accepted promisor remote '%s' not found"), + decoded_remote); + + free(decoded_remote); + } + + strbuf_list_free(accepted_remotes); +} diff --git a/promisor-remote.h b/promisor-remote.h index 88cb599c39..263d331a55 100644 --- a/promisor-remote.h +++ b/promisor-remote.h @@ -9,11 +9,13 @@ struct object_id; * Promisor remote linked list * * Information in its fields come from remote.XXX config entries or - * from extensions.partialclone. + * from extensions.partialclone, except for 'accepted' which comes + * from protocol v2 capabilities exchange. */ struct promisor_remote { struct promisor_remote *next; char *partial_clone_filter; + unsigned int accepted : 1; const char name[FLEX_ARRAY]; }; @@ -32,4 +34,37 @@ void promisor_remote_get_direct(struct repository *repo, const struct object_id *oids, int oid_nr); +/* + * Prepare a "promisor-remote" advertisement by a server. + * Check the value of "promisor.advertise" and maybe the configured + * promisor remotes, if any, to prepare information to send in an + * advertisement. + * Return value is NULL if no promisor remote advertisement should be + * made. Otherwise it contains the names and urls of the advertised + * promisor remotes separated by ';'. See gitprotocol-v2(5). + */ +char *promisor_remote_info(struct repository *repo); + +/* + * Prepare a reply to a "promisor-remote" advertisement from a server. + * Check the value of "promisor.acceptfromserver" and maybe the + * configured promisor remotes, if any, to prepare the reply. + * Return value is NULL if no promisor remote from the server + * is accepted. Otherwise it contains the names of the accepted promisor + * remotes separated by ';'. See gitprotocol-v2(5). + */ +char *promisor_remote_reply(const char *info); + +/* + * Set the 'accepted' flag for some promisor remotes. Useful on the + * server side when some promisor remotes have been accepted by the + * client. + */ +void mark_promisor_remotes_as_accepted(struct repository *repo, const char *remotes); + +/* + * Has any promisor remote been accepted by the client? + */ +int repo_has_accepted_promisor_remote(struct repository *r); + #endif /* PROMISOR_REMOTE_H */ diff --git a/prune-packed.c b/prune-packed.c index d1c65ab10e..7dad2fc0c1 100644 --- a/prune-packed.c +++ b/prune-packed.c @@ -37,7 +37,8 @@ static int prune_object(const struct object_id *oid, const char *path, void prune_packed_objects(int opts) { if (opts & PRUNE_PACKED_VERBOSE) - progress = start_delayed_progress(_("Removing duplicate objects"), 256); + progress = start_delayed_progress(the_repository, + _("Removing duplicate objects"), 256); for_each_loose_file_in_objdir(repo_get_object_directory(the_repository), prune_object, NULL, prune_subdir, &opts); diff --git a/pseudo-merge.c b/pseudo-merge.c index 971f54cfe1..893b763fe4 100644 --- a/pseudo-merge.c +++ b/pseudo-merge.c @@ -459,7 +459,8 @@ void select_pseudo_merges(struct bitmap_writer *writer) return; if (writer->show_progress) - progress = start_progress("Selecting pseudo-merge commits", + progress = start_progress(the_repository, + "Selecting pseudo-merge commits", writer->pseudo_merge_groups.nr); refs_for_each_ref(get_main_ref_store(the_repository), diff --git a/pseudo-merge.h b/pseudo-merge.h index 29df8a32ec..c9fbe9d312 100644 --- a/pseudo-merge.h +++ b/pseudo-merge.h @@ -101,7 +101,7 @@ void select_pseudo_merges(struct bitmap_writer *writer); /* * Represents a serialized view of a file containing pseudo-merge(s) - * (see Documentation/technical/bitmap-format.txt for a specification + * (see Documentation/technical/bitmap-format.adoc for a specification * of the format). */ struct pseudo_merge_map { diff --git a/reachable.c b/reachable.c index ecf7ccf504..9ee04c89ec 100644 --- a/reachable.c +++ b/reachable.c @@ -65,8 +65,10 @@ static void add_rebase_files(struct rev_info *revs) struct worktree **worktrees = get_worktrees(); for (struct worktree **wt = worktrees; *wt; wt++) { + char *wt_gitdir = get_worktree_git_dir(*wt); + strbuf_reset(&buf); - strbuf_addstr(&buf, get_worktree_git_dir(*wt)); + strbuf_addstr(&buf, wt_gitdir); strbuf_complete(&buf, '/'); len = buf.len; for (size_t i = 0; i < ARRAY_SIZE(path); i++) { @@ -74,6 +76,8 @@ static void add_rebase_files(struct rev_info *revs) strbuf_addstr(&buf, path[i]); add_one_file(buf.buf, revs); } + + free(wt_gitdir); } strbuf_release(&buf); free_worktrees(worktrees); diff --git a/read-cache.c b/read-cache.c index 15d79839c2..e678c13e8f 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1523,7 +1523,8 @@ int refresh_index(struct index_state *istate, unsigned int flags, int t2_sum_scan = 0; if (flags & REFRESH_PROGRESS && isatty(2)) - progress = start_delayed_progress(_("Refresh index"), + progress = start_delayed_progress(the_repository, + _("Refresh index"), istate->cache_nr); trace_performance_enter(); @@ -1716,7 +1717,7 @@ int verify_ce_order; static int verify_hdr(const struct cache_header *hdr, unsigned long size) { - git_hash_ctx c; + struct git_hash_ctx c; unsigned char hash[GIT_MAX_RAWSZ]; int hdr_version; unsigned char *start, *end; @@ -1738,8 +1739,8 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size) return 0; the_hash_algo->init_fn(&c); - the_hash_algo->update_fn(&c, hdr, size - the_hash_algo->rawsz); - the_hash_algo->final_fn(hash, &c); + git_hash_update(&c, hdr, size - the_hash_algo->rawsz); + git_hash_final(hash, &c); if (!hasheq(hash, start, the_repository->hash_algo)) return error(_("bad index file sha1 signature")); return 0; @@ -1753,7 +1754,7 @@ static int read_index_extension(struct index_state *istate, istate->cache_tree = cache_tree_read(data, sz); break; case CACHE_EXT_RESOLVE_UNDO: - istate->resolve_undo = resolve_undo_read(data, sz); + istate->resolve_undo = resolve_undo_read(data, sz, the_hash_algo); break; case CACHE_EXT_LINK: if (read_link_extension(istate, data, sz)) @@ -2001,7 +2002,7 @@ static struct index_entry_offset_table *read_ieot_extension(const char *mmap, si static void write_ieot_extension(struct strbuf *sb, struct index_entry_offset_table *ieot); static size_t read_eoie_extension(const char *mmap, size_t mmap_size); -static void write_eoie_extension(struct strbuf *sb, git_hash_ctx *eoie_context, size_t offset); +static void write_eoie_extension(struct strbuf *sb, struct git_hash_ctx *eoie_context, size_t offset); struct load_index_extensions { @@ -2565,7 +2566,7 @@ int repo_index_has_changes(struct repository *repo, } static int write_index_ext_header(struct hashfile *f, - git_hash_ctx *eoie_f, + struct git_hash_ctx *eoie_f, unsigned int ext, unsigned int sz) { @@ -2575,8 +2576,8 @@ static int write_index_ext_header(struct hashfile *f, if (eoie_f) { ext = htonl(ext); sz = htonl(sz); - the_hash_algo->update_fn(eoie_f, &ext, sizeof(ext)); - the_hash_algo->update_fn(eoie_f, &sz, sizeof(sz)); + git_hash_update(eoie_f, &ext, sizeof(ext)); + git_hash_update(eoie_f, &sz, sizeof(sz)); } return 0; } @@ -2830,7 +2831,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, { uint64_t start = getnanotime(); struct hashfile *f; - git_hash_ctx *eoie_c = NULL; + struct git_hash_ctx *eoie_c = NULL; struct cache_header hdr; int i, err = 0, removed, extended, hdr_version; struct cache_entry **cache = istate->cache; @@ -3032,7 +3033,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, istate->resolve_undo) { strbuf_reset(&sb); - resolve_undo_write(&sb, istate->resolve_undo); + resolve_undo_write(&sb, istate->resolve_undo, the_hash_algo); err = write_index_ext_header(f, eoie_c, CACHE_EXT_RESOLVE_UNDO, sb.len) < 0; hashwrite(f, sb.buf, sb.len); @@ -3250,15 +3251,18 @@ static int clean_shared_index_files(const char *current_hex) while ((de = readdir(dir)) != NULL) { const char *sha1_hex; - const char *shared_index_path; + char *shared_index_path; if (!skip_prefix(de->d_name, "sharedindex.", &sha1_hex)) continue; if (!strcmp(sha1_hex, current_hex)) continue; - shared_index_path = git_path("%s", de->d_name); + + shared_index_path = repo_git_path(the_repository, "%s", de->d_name); if (should_delete_shared_index(shared_index_path) > 0 && unlink(shared_index_path)) warning_errno(_("unable to unlink: %s"), shared_index_path); + + free(shared_index_path); } closedir(dir); @@ -3270,6 +3274,7 @@ static int write_shared_index(struct index_state *istate, { struct split_index *si = istate->split_index; int ret, was_full = !istate->sparse_index; + char *path; move_cache_to_base_index(istate); convert_to_sparse(istate, 0); @@ -3285,18 +3290,20 @@ static int write_shared_index(struct index_state *istate, if (ret) return ret; - ret = adjust_shared_perm(get_tempfile_path(*temp)); + ret = adjust_shared_perm(the_repository, get_tempfile_path(*temp)); if (ret) { error(_("cannot fix permission bits on '%s'"), get_tempfile_path(*temp)); return ret; } - ret = rename_tempfile(temp, - git_path("sharedindex.%s", oid_to_hex(&si->base->oid))); + + path = repo_git_path(the_repository, "sharedindex.%s", oid_to_hex(&si->base->oid)); + ret = rename_tempfile(temp, path); if (!ret) { oidcpy(&si->base_oid, &si->base->oid); clean_shared_index_files(oid_to_hex(&si->base->oid)); } + free(path); return ret; } @@ -3377,9 +3384,12 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock, if (new_shared_index) { struct tempfile *temp; int saved_errno; + char *path; /* Same initial permissions as the main .git/index file */ - temp = mks_tempfile_sm(git_path("sharedindex_XXXXXX"), 0, 0666); + path = repo_git_path(the_repository, "sharedindex_XXXXXX"); + temp = mks_tempfile_sm(path, 0, 0666); + free(path); if (!temp) { ret = do_write_locked_index(istate, lock, flags, ~WRITE_SPLIT_INDEX_EXTENSION); @@ -3400,9 +3410,10 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock, /* Freshen the shared index only if the split-index was written */ if (!ret && !new_shared_index && !is_null_oid(&si->base_oid)) { - const char *shared_index = git_path("sharedindex.%s", - oid_to_hex(&si->base_oid)); + char *shared_index = repo_git_path(the_repository, "sharedindex.%s", + oid_to_hex(&si->base_oid)); freshen_shared_index(shared_index, 1); + free(shared_index); } out: @@ -3578,7 +3589,7 @@ static size_t read_eoie_extension(const char *mmap, size_t mmap_size) uint32_t extsize; size_t offset, src_offset; unsigned char hash[GIT_MAX_RAWSZ]; - git_hash_ctx c; + struct git_hash_ctx c; /* ensure we have an index big enough to contain an EOIE extension */ if (mmap_size < sizeof(struct cache_header) + EOIE_SIZE_WITH_HEADER + the_hash_algo->rawsz) @@ -3633,12 +3644,12 @@ static size_t read_eoie_extension(const char *mmap, size_t mmap_size) if (src_offset + 8 + extsize < src_offset) return 0; - the_hash_algo->update_fn(&c, mmap + src_offset, 8); + git_hash_update(&c, mmap + src_offset, 8); src_offset += 8; src_offset += extsize; } - the_hash_algo->final_fn(hash, &c); + git_hash_final(hash, &c); if (!hasheq(hash, (const unsigned char *)index, the_repository->hash_algo)) return 0; @@ -3649,7 +3660,7 @@ static size_t read_eoie_extension(const char *mmap, size_t mmap_size) return offset; } -static void write_eoie_extension(struct strbuf *sb, git_hash_ctx *eoie_context, size_t offset) +static void write_eoie_extension(struct strbuf *sb, struct git_hash_ctx *eoie_context, size_t offset) { uint32_t buffer; unsigned char hash[GIT_MAX_RAWSZ]; @@ -3659,7 +3670,7 @@ static void write_eoie_extension(struct strbuf *sb, git_hash_ctx *eoie_context, strbuf_add(sb, &buffer, sizeof(uint32_t)); /* hash */ - the_hash_algo->final_fn(hash, eoie_context); + git_hash_final(hash, eoie_context); strbuf_add(sb, hash, the_hash_algo->rawsz); } diff --git a/ref-filter.c b/ref-filter.c index 23054694c2..6da8d4c03b 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -235,6 +235,10 @@ static struct used_atom { enum { S_BARE, S_GRADE, S_SIGNER, S_KEY, S_FINGERPRINT, S_PRI_KEY_FP, S_TRUST_LEVEL } option; } signature; + struct { + char *name; + struct commit *commit; + } base; struct strvec describe_args; struct refname_atom refname; char *head; @@ -891,35 +895,30 @@ static int rest_atom_parser(struct ref_format *format UNUSED, return 0; } -static int ahead_behind_atom_parser(struct ref_format *format, - struct used_atom *atom UNUSED, +static int ahead_behind_atom_parser(struct ref_format *format UNUSED, + struct used_atom *atom, const char *arg, struct strbuf *err) { - struct string_list_item *item; - if (!arg) return strbuf_addf_ret(err, -1, _("expected format: %%(ahead-behind:<committish>)")); - item = string_list_append(&format->bases, arg); - item->util = lookup_commit_reference_by_name(arg); - if (!item->util) + atom->u.base.commit = lookup_commit_reference_by_name(arg); + if (!atom->u.base.commit) die("failed to find '%s'", arg); return 0; } -static int is_base_atom_parser(struct ref_format *format, - struct used_atom *atom UNUSED, +static int is_base_atom_parser(struct ref_format *format UNUSED, + struct used_atom *atom, const char *arg, struct strbuf *err) { - struct string_list_item *item; - if (!arg) return strbuf_addf_ret(err, -1, _("expected format: %%(is-base:<committish>)")); - item = string_list_append(&format->is_base_tips, arg); - item->util = lookup_commit_reference_by_name(arg); - if (!item->util) + atom->u.base.name = xstrdup(arg); + atom->u.base.commit = lookup_commit_reference_by_name(arg); + if (!atom->u.base.commit) die("failed to find '%s'", arg); return 0; @@ -3009,6 +3008,8 @@ void ref_array_clear(struct ref_array *array) free(atom->u.head); else if (atom->atom_type == ATOM_DESCRIBE) strvec_clear(&atom->u.describe_args); + else if (atom->atom_type == ATOM_ISBASE) + free(atom->u.base.name); else if (atom->atom_type == ATOM_TRAILERS || (atom->atom_type == ATOM_CONTENTS && atom->u.contents.option == C_TRAILERS)) { @@ -3041,7 +3042,7 @@ static void reach_filter(struct ref_array *array, struct commit_list **check_reachable, int include_reached) { - int i, old_nr; + size_t i, old_nr; struct commit **to_clear; if (!*check_reachable) @@ -3084,22 +3085,30 @@ static void reach_filter(struct ref_array *array, } void filter_ahead_behind(struct repository *r, - struct ref_format *format, struct ref_array *array) { struct commit **commits; - size_t commits_nr = format->bases.nr + array->nr; + size_t bases_nr, commits_nr; + + if (!array->nr) + return; - if (!format->bases.nr || !array->nr) + for (size_t i = bases_nr = 0; i < used_atom_cnt; i++) { + if (used_atom[i].atom_type == ATOM_AHEADBEHIND) + bases_nr++; + } + if (!bases_nr) return; - ALLOC_ARRAY(commits, commits_nr); - for (size_t i = 0; i < format->bases.nr; i++) - commits[i] = format->bases.items[i].util; + ALLOC_ARRAY(commits, st_add(bases_nr, array->nr)); + for (size_t i = 0, j = 0; i < used_atom_cnt; i++) { + if (used_atom[i].atom_type == ATOM_AHEADBEHIND) + commits[j++] = used_atom[i].u.base.commit; + } - ALLOC_ARRAY(array->counts, st_mult(format->bases.nr, array->nr)); + ALLOC_ARRAY(array->counts, st_mult(bases_nr, array->nr)); - commits_nr = format->bases.nr; + commits_nr = bases_nr; array->counts_nr = 0; for (size_t i = 0; i < array->nr; i++) { const char *name = array->items[i]->refname; @@ -3108,8 +3117,8 @@ void filter_ahead_behind(struct repository *r, if (!commits[commits_nr]) continue; - CALLOC_ARRAY(array->items[i]->counts, format->bases.nr); - for (size_t j = 0; j < format->bases.nr; j++) { + CALLOC_ARRAY(array->items[i]->counts, bases_nr); + for (size_t j = 0; j < bases_nr; j++) { struct ahead_behind_count *count; count = &array->counts[array->counts_nr++]; count->tip_index = commits_nr; @@ -3125,14 +3134,20 @@ void filter_ahead_behind(struct repository *r, } void filter_is_base(struct repository *r, - struct ref_format *format, struct ref_array *array) { struct commit **bases; - size_t bases_nr = 0; + size_t bases_nr = 0, is_base_nr; struct ref_array_item **back_index; - if (!format->is_base_tips.nr || !array->nr) + if (!array->nr) + return; + + for (size_t i = is_base_nr = 0; i < used_atom_cnt; i++) { + if (used_atom[i].atom_type == ATOM_ISBASE) + is_base_nr++; + } + if (!is_base_nr) return; CALLOC_ARRAY(back_index, array->nr); @@ -3142,7 +3157,7 @@ void filter_is_base(struct repository *r, const char *name = array->items[i]->refname; struct commit *c = lookup_commit_reference_by_name_gently(name, 1); - CALLOC_ARRAY(array->items[i]->is_base, format->is_base_tips.nr); + CALLOC_ARRAY(array->items[i]->is_base, is_base_nr); if (!c) continue; @@ -3152,15 +3167,20 @@ void filter_is_base(struct repository *r, bases_nr++; } - for (size_t i = 0; i < format->is_base_tips.nr; i++) { - struct commit *tip = format->is_base_tips.items[i].util; - int base_index = get_branch_base_for_tip(r, tip, bases, bases_nr); + for (size_t i = 0, j = 0; i < used_atom_cnt; i++) { + struct commit *tip; + int base_index; + + if (used_atom[i].atom_type != ATOM_ISBASE) + continue; + tip = used_atom[i].u.base.commit; + base_index = get_branch_base_for_tip(r, tip, bases, bases_nr); if (base_index < 0) continue; /* Store the string for use in output later. */ - back_index[base_index]->is_base[i] = xstrdup(format->is_base_tips.items[i].string); + back_index[base_index]->is_base[j++] = xstrdup(used_atom[i].u.base.name); } free(back_index); @@ -3252,8 +3272,7 @@ struct ref_sorting { }; static inline int can_do_iterative_format(struct ref_filter *filter, - struct ref_sorting *sorting, - struct ref_format *format) + struct ref_sorting *sorting) { /* * Reference backends sort patterns lexicographically by refname, so if @@ -3277,17 +3296,20 @@ static inline int can_do_iterative_format(struct ref_filter *filter, * - filtering on reachability * - including ahead-behind information in the formatted output */ - return !(filter->reachable_from || - filter->unreachable_from || - format->bases.nr || - format->is_base_tips.nr); + for (size_t i = 0; i < used_atom_cnt; i++) { + if (used_atom[i].atom_type == ATOM_AHEADBEHIND) + return 0; + if (used_atom[i].atom_type == ATOM_ISBASE) + return 0; + } + return !(filter->reachable_from || filter->unreachable_from); } void filter_and_format_refs(struct ref_filter *filter, unsigned int type, struct ref_sorting *sorting, struct ref_format *format) { - if (can_do_iterative_format(filter, sorting, format)) { + if (can_do_iterative_format(filter, sorting)) { int save_commit_buffer_orig; struct ref_filter_and_format_cbdata ref_cbdata = { .filter = filter, @@ -3303,8 +3325,8 @@ void filter_and_format_refs(struct ref_filter *filter, unsigned int type, } else { struct ref_array array = { 0 }; filter_refs(&array, filter, type); - filter_ahead_behind(the_repository, format, &array); - filter_is_base(the_repository, format, &array); + filter_ahead_behind(the_repository, &array); + filter_is_base(the_repository, &array); ref_array_sort(sorting, &array); print_formatted_ref_array(&array, format); ref_array_clear(&array); @@ -3638,16 +3660,3 @@ void ref_filter_clear(struct ref_filter *filter) free_commit_list(filter->unreachable_from); ref_filter_init(filter); } - -void ref_format_init(struct ref_format *format) -{ - struct ref_format blank = REF_FORMAT_INIT; - memcpy(format, &blank, sizeof(blank)); -} - -void ref_format_clear(struct ref_format *format) -{ - string_list_clear(&format->bases, 0); - string_list_clear(&format->is_base_tips, 0); - ref_format_init(format); -} diff --git a/ref-filter.h b/ref-filter.h index 754038ab07..013d4cfa64 100644 --- a/ref-filter.h +++ b/ref-filter.h @@ -99,12 +99,6 @@ struct ref_format { /* Internal state to ref-filter */ int need_color_reset_at_eol; - /* List of bases for ahead-behind counts. */ - struct string_list bases; - - /* List of bases for is-base indicators. */ - struct string_list is_base_tips; - struct { int max_count; int omit_empty; @@ -117,8 +111,6 @@ struct ref_format { } #define REF_FORMAT_INIT { \ .use_color = -1, \ - .bases = STRING_LIST_INIT_DUP, \ - .is_base_tips = STRING_LIST_INIT_DUP, \ } /* Macros for checking --merged and --no-merged options */ @@ -205,7 +197,6 @@ struct ref_array_item *ref_array_push(struct ref_array *array, * If this is not called, then any ahead-behind atoms will be blank. */ void filter_ahead_behind(struct repository *r, - struct ref_format *format, struct ref_array *array); /* @@ -215,13 +206,9 @@ void filter_ahead_behind(struct repository *r, * If this is not called, then any is-base atoms will be blank. */ void filter_is_base(struct repository *r, - struct ref_format *format, struct ref_array *array); void ref_filter_init(struct ref_filter *filter); void ref_filter_clear(struct ref_filter *filter); -void ref_format_init(struct ref_format *format); -void ref_format_clear(struct ref_format *format); - #endif /* REF_FILTER_H */ @@ -1318,19 +1318,27 @@ int ref_transaction_update(struct ref_transaction *transaction, return 0; } -int ref_transaction_update_reflog(struct ref_transaction *transaction, - const char *refname, - const struct object_id *new_oid, - const struct object_id *old_oid, - const char *committer_info, unsigned int flags, - const char *msg, unsigned int index, - struct strbuf *err) +/* + * Similar to`ref_transaction_update`, but this function is only for adding + * a reflog update. Supports providing custom committer information. The index + * field can be utiltized to order updates as desired. When not used, the + * updates default to being ordered by refname. + */ +static int ref_transaction_update_reflog(struct ref_transaction *transaction, + const char *refname, + const struct object_id *new_oid, + const struct object_id *old_oid, + const char *committer_info, + unsigned int flags, + const char *msg, + uint64_t index, + struct strbuf *err) { struct ref_update *update; assert(err); - flags |= REF_LOG_ONLY | REF_NO_DEREF; + flags |= REF_LOG_ONLY | REF_FORCE_CREATE_REFLOG | REF_NO_DEREF; if (!transaction_refname_valid(refname, new_oid, flags, err)) return -1; @@ -1345,6 +1353,13 @@ int ref_transaction_update_reflog(struct ref_transaction *transaction, update->flags &= ~REF_HAVE_OLD; update->index = index; + /* + * Reference backends may need to know the max index to optimize + * their writes. So we store the max_index on the transaction level. + */ + if (index > transaction->max_index) + transaction->max_index = index; + return 0; } @@ -1684,6 +1699,24 @@ struct ref_iterator *refs_ref_iterator_begin( enum do_for_each_ref_flags flags) { struct ref_iterator *iter; + struct strvec normalized_exclude_patterns = STRVEC_INIT; + + if (exclude_patterns) { + for (size_t i = 0; exclude_patterns[i]; i++) { + const char *pattern = exclude_patterns[i]; + size_t len = strlen(pattern); + if (!len) + continue; + + if (pattern[len - 1] == '/') + strvec_push(&normalized_exclude_patterns, pattern); + else + strvec_pushf(&normalized_exclude_patterns, "%s/", + pattern); + } + + exclude_patterns = normalized_exclude_patterns.v; + } if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) { static int ref_paranoia = -1; @@ -1704,6 +1737,8 @@ struct ref_iterator *refs_ref_iterator_begin( if (trim) iter = prefix_ref_iterator_begin(iter, "", trim); + strvec_clear(&normalized_exclude_patterns); + return iter; } @@ -2139,7 +2174,7 @@ struct ref_store *repo_get_submodule_ref_store(struct repository *repo, if (!is_nonbare_repository_dir(&submodule_sb)) goto done; - if (submodule_to_gitdir(&submodule_sb, submodule)) + if (submodule_to_gitdir(repo, &submodule_sb, submodule)) goto done; subrepo = xmalloc(sizeof(*subrepo)); @@ -2177,8 +2212,8 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt) if (wt->id) { struct strbuf common_path = STRBUF_INIT; - strbuf_git_common_path(&common_path, wt->repo, - "worktrees/%s", wt->id); + repo_common_path_append(wt->repo, &common_path, + "worktrees/%s", wt->id); refs = ref_store_init(wt->repo, wt->repo->ref_storage_format, common_path.buf, REF_STORE_ALL_CAPS); strbuf_release(&common_path); @@ -2460,19 +2495,18 @@ int ref_transaction_commit(struct ref_transaction *transaction, return ret; } -int refs_verify_refname_available(struct ref_store *refs, - const char *refname, - const struct string_list *extras, - const struct string_list *skip, - unsigned int initial_transaction, - struct strbuf *err) +int refs_verify_refnames_available(struct ref_store *refs, + const struct string_list *refnames, + const struct string_list *extras, + const struct string_list *skip, + unsigned int initial_transaction, + struct strbuf *err) { - const char *slash; - const char *extra_refname; struct strbuf dirname = STRBUF_INIT; struct strbuf referent = STRBUF_INIT; - struct object_id oid; - unsigned int type; + struct string_list_item *item; + struct ref_iterator *iter = NULL; + struct strset dirnames; int ret = -1; /* @@ -2482,86 +2516,130 @@ int refs_verify_refname_available(struct ref_store *refs, assert(err); - strbuf_grow(&dirname, strlen(refname) + 1); - for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) { - /* - * Just saying "Is a directory" when we e.g. can't - * lock some multi-level ref isn't very informative, - * the user won't be told *what* is a directory, so - * let's not use strerror() below. - */ - int ignore_errno; - /* Expand dirname to the new prefix, not including the trailing slash: */ - strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len); + strset_init(&dirnames); + + for_each_string_list_item(item, refnames) { + const char *refname = item->string; + const char *extra_refname; + struct object_id oid; + unsigned int type; + const char *slash; + + strbuf_reset(&dirname); + + for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) { + /* + * Just saying "Is a directory" when we e.g. can't + * lock some multi-level ref isn't very informative, + * the user won't be told *what* is a directory, so + * let's not use strerror() below. + */ + int ignore_errno; + + /* Expand dirname to the new prefix, not including the trailing slash: */ + strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len); + + /* + * We are still at a leading dir of the refname (e.g., + * "refs/foo"; if there is a reference with that name, + * it is a conflict, *unless* it is in skip. + */ + if (skip && string_list_has_string(skip, dirname.buf)) + continue; + + /* + * If we've already seen the directory we don't need to + * process it again. Skip it to avoid checking checking + * common prefixes like "refs/heads/" repeatedly. + */ + if (!strset_add(&dirnames, dirname.buf)) + continue; + + if (!initial_transaction && + !refs_read_raw_ref(refs, dirname.buf, &oid, &referent, + &type, &ignore_errno)) { + strbuf_addf(err, _("'%s' exists; cannot create '%s'"), + dirname.buf, refname); + goto cleanup; + } + + if (extras && string_list_has_string(extras, dirname.buf)) { + strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"), + refname, dirname.buf); + goto cleanup; + } + } /* - * We are still at a leading dir of the refname (e.g., - * "refs/foo"; if there is a reference with that name, - * it is a conflict, *unless* it is in skip. + * We are at the leaf of our refname (e.g., "refs/foo/bar"). + * There is no point in searching for a reference with that + * name, because a refname isn't considered to conflict with + * itself. But we still need to check for references whose + * names are in the "refs/foo/bar/" namespace, because they + * *do* conflict. */ - if (skip && string_list_has_string(skip, dirname.buf)) - continue; + strbuf_addstr(&dirname, refname + dirname.len); + strbuf_addch(&dirname, '/'); - if (!initial_transaction && - !refs_read_raw_ref(refs, dirname.buf, &oid, &referent, - &type, &ignore_errno)) { - strbuf_addf(err, _("'%s' exists; cannot create '%s'"), - dirname.buf, refname); - goto cleanup; - } + if (!initial_transaction) { + int ok; - if (extras && string_list_has_string(extras, dirname.buf)) { - strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"), - refname, dirname.buf); - goto cleanup; - } - } + if (!iter) { + iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0, + DO_FOR_EACH_INCLUDE_BROKEN); + } else if (ref_iterator_seek(iter, dirname.buf) < 0) { + goto cleanup; + } - /* - * We are at the leaf of our refname (e.g., "refs/foo/bar"). - * There is no point in searching for a reference with that - * name, because a refname isn't considered to conflict with - * itself. But we still need to check for references whose - * names are in the "refs/foo/bar/" namespace, because they - * *do* conflict. - */ - strbuf_addstr(&dirname, refname + dirname.len); - strbuf_addch(&dirname, '/'); - - if (!initial_transaction) { - struct ref_iterator *iter; - int ok; - - iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0, - DO_FOR_EACH_INCLUDE_BROKEN); - while ((ok = ref_iterator_advance(iter)) == ITER_OK) { - if (skip && - string_list_has_string(skip, iter->refname)) - continue; + while ((ok = ref_iterator_advance(iter)) == ITER_OK) { + if (skip && + string_list_has_string(skip, iter->refname)) + continue; - strbuf_addf(err, _("'%s' exists; cannot create '%s'"), - iter->refname, refname); - ref_iterator_abort(iter); - goto cleanup; + strbuf_addf(err, _("'%s' exists; cannot create '%s'"), + iter->refname, refname); + goto cleanup; + } + + if (ok != ITER_DONE) + BUG("error while iterating over references"); } - if (ok != ITER_DONE) - BUG("error while iterating over references"); + extra_refname = find_descendant_ref(dirname.buf, extras, skip); + if (extra_refname) { + strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"), + refname, extra_refname); + goto cleanup; + } } - extra_refname = find_descendant_ref(dirname.buf, extras, skip); - if (extra_refname) - strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"), - refname, extra_refname); - else - ret = 0; + ret = 0; cleanup: strbuf_release(&referent); strbuf_release(&dirname); + strset_clear(&dirnames); + ref_iterator_free(iter); return ret; } +int refs_verify_refname_available(struct ref_store *refs, + const char *refname, + const struct string_list *extras, + const struct string_list *skip, + unsigned int initial_transaction, + struct strbuf *err) +{ + struct string_list_item item = { .string = (char *) refname }; + struct string_list refnames = { + .items = &item, + .nr = 1, + }; + + return refs_verify_refnames_available(refs, &refnames, extras, skip, + initial_transaction, err); +} + struct do_for_each_reflog_help { each_reflog_fn *fn; void *cb_data; @@ -2798,7 +2876,7 @@ done: } struct reflog_migration_data { - unsigned int index; + uint64_t index; const char *refname; struct ref_store *old_refs; struct ref_transaction *transaction; @@ -3028,9 +3106,11 @@ int repo_migrate_ref_storage_format(struct repository *repo, if (ret < 0) goto done; - ret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data); - if (ret < 0) - goto done; + if (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) { + ret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data); + if (ret < 0) + goto done; + } ret = ref_transaction_commit(transaction, errbuf); if (ret < 0) @@ -124,6 +124,18 @@ int refs_verify_refname_available(struct ref_store *refs, unsigned int initial_transaction, struct strbuf *err); +/* + * Same as `refs_verify_refname_available()`, but checking for a list of + * refnames instead of only a single item. This is more efficient in the case + * where one needs to check multiple refnames. + */ +int refs_verify_refnames_available(struct ref_store *refs, + const struct string_list *refnames, + const struct string_list *extras, + const struct string_list *skip, + unsigned int initial_transaction, + struct strbuf *err); + int refs_ref_exists(struct ref_store *refs, const char *refname); int should_autocreate_reflog(enum log_refs_config log_all_ref_updates, @@ -577,7 +589,7 @@ int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_dat /* * Return 0 iff refname has the correct format for a refname according - * to the rules described in Documentation/git-check-ref-format.txt. + * to the rules described in Documentation/git-check-ref-format.adoc. * If REFNAME_ALLOW_ONELEVEL is set in flags, then accept one-level * reference names. If REFNAME_REFSPEC_PATTERN is set in flags, then * allow a single "*" wildcard character in the refspec. No leading or @@ -772,20 +784,6 @@ int ref_transaction_update(struct ref_transaction *transaction, struct strbuf *err); /* - * Similar to`ref_transaction_update`, but this function is only for adding - * a reflog update. Supports providing custom committer information. The index - * field can be utiltized to order updates as desired. When not used, the - * updates default to being ordered by refname. - */ -int ref_transaction_update_reflog(struct ref_transaction *transaction, - const char *refname, - const struct object_id *new_oid, - const struct object_id *old_oid, - const char *committer_info, unsigned int flags, - const char *msg, unsigned int index, - struct strbuf *err); - -/* * Add a reference creation to transaction. new_oid is the value that * the reference should have after the update; it must not be * null_oid. It is verified that the reference does not exist @@ -1157,8 +1155,11 @@ int is_pseudo_ref(const char *refname); * - REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN: perform a dry-run migration * without touching the main repository. The result will be written into a * temporary ref storage directory. + * + * - REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG: skip migration of reflogs. */ -#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0) +#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0) +#define REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG (1 << 1) /* * Migrate the ref storage format used by the repository to the diff --git a/refs/debug.c b/refs/debug.c index fbc4df08b4..5390fa9c18 100644 --- a/refs/debug.c +++ b/refs/debug.c @@ -169,6 +169,16 @@ static int debug_ref_iterator_advance(struct ref_iterator *ref_iterator) return res; } +static int debug_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct debug_ref_iterator *diter = + (struct debug_ref_iterator *)ref_iterator; + int res = diter->iter->vtable->seek(diter->iter, prefix); + trace_printf_key(&trace_refs, "iterator_seek: %s: %d\n", prefix ? prefix : "", res); + return res; +} + static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -179,19 +189,19 @@ static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator, return res; } -static int debug_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void debug_ref_iterator_release(struct ref_iterator *ref_iterator) { struct debug_ref_iterator *diter = (struct debug_ref_iterator *)ref_iterator; - int res = diter->iter->vtable->abort(diter->iter); - trace_printf_key(&trace_refs, "iterator_abort: %d\n", res); - return res; + diter->iter->vtable->release(diter->iter); + trace_printf_key(&trace_refs, "iterator_abort\n"); } static struct ref_iterator_vtable debug_ref_iterator_vtable = { .advance = debug_ref_iterator_advance, + .seek = debug_ref_iterator_seek, .peel = debug_ref_iterator_peel, - .abort = debug_ref_iterator_abort, + .release = debug_ref_iterator_release, }; static struct ref_iterator * diff --git a/refs/files-backend.c b/refs/files-backend.c index 5cfb8b7ca8..ff54a4bb7e 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -678,6 +678,7 @@ static void unlock_ref(struct ref_lock *lock) */ static int lock_raw_ref(struct files_ref_store *refs, const char *refname, int mustexist, + struct string_list *refnames_to_check, const struct string_list *extras, struct ref_lock **lock_p, struct strbuf *referent, @@ -855,16 +856,11 @@ retry: } /* - * If the ref did not exist and we are creating it, - * make sure there is no existing packed ref that - * conflicts with refname: + * If the ref did not exist and we are creating it, we have to + * make sure there is no existing packed ref that conflicts + * with refname. This check is deferred so that we can batch it. */ - if (refs_verify_refname_available( - refs->packed_ref_store, refname, - extras, NULL, 0, err)) { - ret = TRANSACTION_NAME_CONFLICT; - goto error_return; - } + string_list_append(refnames_to_check, refname); } ret = 0; @@ -919,13 +915,17 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator) return ITER_OK; } - iter->iter0 = NULL; - if (ref_iterator_abort(ref_iterator) != ITER_DONE) - ok = ITER_ERROR; - return ok; } +static int files_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct files_ref_iterator *iter = + (struct files_ref_iterator *)ref_iterator; + return ref_iterator_seek(iter->iter0, prefix); +} + static int files_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -935,23 +935,18 @@ static int files_ref_iterator_peel(struct ref_iterator *ref_iterator, return ref_iterator_peel(iter->iter0, peeled); } -static int files_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void files_ref_iterator_release(struct ref_iterator *ref_iterator) { struct files_ref_iterator *iter = (struct files_ref_iterator *)ref_iterator; - int ok = ITER_DONE; - - if (iter->iter0) - ok = ref_iterator_abort(iter->iter0); - - base_ref_iterator_free(ref_iterator); - return ok; + ref_iterator_free(iter->iter0); } static struct ref_iterator_vtable files_ref_iterator_vtable = { .advance = files_ref_iterator_advance, + .seek = files_ref_iterator_seek, .peel = files_ref_iterator_peel, - .abort = files_ref_iterator_abort, + .release = files_ref_iterator_release, }; static struct ref_iterator *files_ref_iterator_begin( @@ -1382,7 +1377,7 @@ static int should_pack_refs(struct files_ref_store *refs, iter->flags, opts)) refcount++; if (refcount >= limit) { - ref_iterator_abort(iter); + ref_iterator_free(iter); return 1; } } @@ -1390,6 +1385,7 @@ static int should_pack_refs(struct files_ref_store *refs, if (ret != ITER_DONE) die("error while iterating over references"); + ref_iterator_free(iter); return 0; } @@ -1456,6 +1452,7 @@ static int files_pack_refs(struct ref_store *ref_store, packed_refs_unlock(refs->packed_ref_store); prune_refs(refs, &refs_to_prune); + ref_iterator_free(iter); strbuf_release(&err); return 0; } @@ -1831,7 +1828,7 @@ static int log_ref_setup(struct files_ref_store *refs, } if (*logfd >= 0) - adjust_shared_perm(logfile); + adjust_shared_perm(the_repository, logfile); free(logfile); return 0; @@ -2303,35 +2300,33 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator) return ITER_OK; } - iter->dir_iterator = NULL; - if (ref_iterator_abort(ref_iterator) == ITER_ERROR) - ok = ITER_ERROR; return ok; } +static int files_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSED, + const char *prefix UNUSED) +{ + BUG("ref_iterator_seek() called for reflog_iterator"); +} + static int files_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED, struct object_id *peeled UNUSED) { BUG("ref_iterator_peel() called for reflog_iterator"); } -static int files_reflog_iterator_abort(struct ref_iterator *ref_iterator) +static void files_reflog_iterator_release(struct ref_iterator *ref_iterator) { struct files_reflog_iterator *iter = (struct files_reflog_iterator *)ref_iterator; - int ok = ITER_DONE; - - if (iter->dir_iterator) - ok = dir_iterator_abort(iter->dir_iterator); - - base_ref_iterator_free(ref_iterator); - return ok; + dir_iterator_free(iter->dir_iterator); } static struct ref_iterator_vtable files_reflog_iterator_vtable = { .advance = files_reflog_iterator_advance, + .seek = files_reflog_iterator_seek, .peel = files_reflog_iterator_peel, - .abort = files_reflog_iterator_abort, + .release = files_reflog_iterator_release, }; static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store, @@ -2569,6 +2564,7 @@ static int lock_ref_for_update(struct files_ref_store *refs, struct ref_update *update, struct ref_transaction *transaction, const char *head_ref, + struct string_list *refnames_to_check, struct string_list *affected_refnames, struct strbuf *err) { @@ -2597,7 +2593,7 @@ static int lock_ref_for_update(struct files_ref_store *refs, lock->count++; } else { ret = lock_raw_ref(refs, update->refname, mustexist, - affected_refnames, + refnames_to_check, affected_refnames, &lock, &referent, &update->type, err); if (ret) { @@ -2615,9 +2611,6 @@ static int lock_ref_for_update(struct files_ref_store *refs, update->backend_data = lock; - if (update->flags & REF_LOG_ONLY) - goto out; - if (update->type & REF_ISSYMREF) { if (update->flags & REF_NO_DEREF) { /* @@ -2814,6 +2807,7 @@ static int files_transaction_prepare(struct ref_store *ref_store, size_t i; int ret = 0; struct string_list affected_refnames = STRING_LIST_INIT_NODUP; + struct string_list refnames_to_check = STRING_LIST_INIT_NODUP; char *head_ref = NULL; int head_type; struct files_transaction_backend_data *backend_data; @@ -2901,7 +2895,8 @@ static int files_transaction_prepare(struct ref_store *ref_store, struct ref_update *update = transaction->updates[i]; ret = lock_ref_for_update(refs, update, transaction, - head_ref, &affected_refnames, err); + head_ref, &refnames_to_check, + &affected_refnames, err); if (ret) goto cleanup; @@ -2933,6 +2928,26 @@ static int files_transaction_prepare(struct ref_store *ref_store, } } + /* + * Verify that none of the loose reference that we're about to write + * conflict with any existing packed references. Ideally, we'd do this + * check after the packed-refs are locked so that the file cannot + * change underneath our feet. But introducing such a lock now would + * probably do more harm than good as users rely on there not being a + * global lock with the "files" backend. + * + * Another alternative would be to do the check after the (optional) + * lock, but that would extend the time we spend in the globally-locked + * state. + * + * So instead, we accept the race for now. + */ + if (refs_verify_refnames_available(refs->packed_ref_store, &refnames_to_check, + &affected_refnames, NULL, 0, err)) { + ret = TRANSACTION_NAME_CONFLICT; + goto cleanup; + } + if (packed_transaction) { if (packed_refs_lock(refs->packed_ref_store, 0, err)) { ret = TRANSACTION_GENERIC_ERROR; @@ -2975,6 +2990,7 @@ static int files_transaction_prepare(struct ref_store *ref_store, cleanup: free(head_ref); string_list_clear(&affected_refnames, 0); + string_list_clear(&refnames_to_check, 0); if (ret) files_transaction_cleanup(refs, transaction); @@ -3039,6 +3055,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs, size_t i; int ret = 0; struct string_list affected_refnames = STRING_LIST_INIT_NODUP; + struct string_list refnames_to_check = STRING_LIST_INIT_NODUP; struct ref_transaction *packed_transaction = NULL; struct ref_transaction *loose_transaction = NULL; @@ -3088,11 +3105,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs, !is_null_oid(&update->old_oid)) BUG("initial ref transaction with old_sha1 set"); - if (refs_verify_refname_available(&refs->base, update->refname, - &affected_refnames, NULL, 1, err)) { - ret = TRANSACTION_NAME_CONFLICT; - goto cleanup; - } + string_list_append(&refnames_to_check, update->refname); /* * packed-refs don't support symbolic refs, root refs and reflogs, @@ -3128,8 +3141,19 @@ static int files_transaction_finish_initial(struct files_ref_store *refs, } } - if (packed_refs_lock(refs->packed_ref_store, 0, err) || - ref_transaction_commit(packed_transaction, err)) { + if (packed_refs_lock(refs->packed_ref_store, 0, err)) { + ret = TRANSACTION_GENERIC_ERROR; + goto cleanup; + } + + if (refs_verify_refnames_available(&refs->base, &refnames_to_check, + &affected_refnames, NULL, 1, err)) { + packed_refs_unlock(refs->packed_ref_store); + ret = TRANSACTION_NAME_CONFLICT; + goto cleanup; + } + + if (ref_transaction_commit(packed_transaction, err)) { ret = TRANSACTION_GENERIC_ERROR; goto cleanup; } @@ -3150,6 +3174,7 @@ cleanup: ref_transaction_free(packed_transaction); transaction->state = REF_TRANSACTION_CLOSED; string_list_clear(&affected_refnames, 0); + string_list_clear(&refnames_to_check, 0); return ret; } @@ -3491,8 +3516,8 @@ static int files_ref_store_create_on_disk(struct ref_store *ref_store, * they do not understand the reference format extension. */ strbuf_addf(&sb, "%s/refs", ref_store->gitdir); - safe_create_dir(sb.buf, 1); - adjust_shared_perm(sb.buf); + safe_create_dir(the_repository, sb.buf, 1); + adjust_shared_perm(the_repository, sb.buf); /* * There is no need to create directories for common refs when creating @@ -3504,11 +3529,11 @@ static int files_ref_store_create_on_disk(struct ref_store *ref_store, */ strbuf_reset(&sb); files_ref_path(refs, &sb, "refs/heads"); - safe_create_dir(sb.buf, 1); + safe_create_dir(the_repository, sb.buf, 1); strbuf_reset(&sb); files_ref_path(refs, &sb, "refs/tags"); - safe_create_dir(sb.buf, 1); + safe_create_dir(the_repository, sb.buf, 1); } strbuf_release(&sb); @@ -3811,6 +3836,7 @@ static int files_fsck_refs_dir(struct ref_store *ref_store, ret = error(_("failed to iterate over '%s'"), sb.buf); out: + dir_iterator_free(iter); strbuf_release(&sb); strbuf_release(&refname); return ret; diff --git a/refs/iterator.c b/refs/iterator.c index d25e568bf0..766d96e795 100644 --- a/refs/iterator.c +++ b/refs/iterator.c @@ -15,15 +15,26 @@ int ref_iterator_advance(struct ref_iterator *ref_iterator) return ref_iterator->vtable->advance(ref_iterator); } +int ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + return ref_iterator->vtable->seek(ref_iterator, prefix); +} + int ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { return ref_iterator->vtable->peel(ref_iterator, peeled); } -int ref_iterator_abort(struct ref_iterator *ref_iterator) +void ref_iterator_free(struct ref_iterator *ref_iterator) { - return ref_iterator->vtable->abort(ref_iterator); + if (ref_iterator) { + ref_iterator->vtable->release(ref_iterator); + /* Help make use-after-free bugs fail quickly: */ + ref_iterator->vtable = NULL; + free(ref_iterator); + } } void base_ref_iterator_init(struct ref_iterator *iter, @@ -36,20 +47,19 @@ void base_ref_iterator_init(struct ref_iterator *iter, iter->flags = 0; } -void base_ref_iterator_free(struct ref_iterator *iter) -{ - /* Help make use-after-free bugs fail quickly: */ - iter->vtable = NULL; - free(iter); -} - struct empty_ref_iterator { struct ref_iterator base; }; -static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator) +static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator UNUSED) +{ + return ITER_DONE; +} + +static int empty_ref_iterator_seek(struct ref_iterator *ref_iterator UNUSED, + const char *prefix UNUSED) { - return ref_iterator_abort(ref_iterator); + return 0; } static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator UNUSED, @@ -58,16 +68,15 @@ static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator UNUSED, BUG("peel called for empty iterator"); } -static int empty_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void empty_ref_iterator_release(struct ref_iterator *ref_iterator UNUSED) { - base_ref_iterator_free(ref_iterator); - return ITER_DONE; } static struct ref_iterator_vtable empty_ref_iterator_vtable = { .advance = empty_ref_iterator_advance, + .seek = empty_ref_iterator_seek, .peel = empty_ref_iterator_peel, - .abort = empty_ref_iterator_abort, + .release = empty_ref_iterator_release, }; struct ref_iterator *empty_ref_iterator_begin(void) @@ -87,7 +96,8 @@ int is_empty_ref_iterator(struct ref_iterator *ref_iterator) struct merge_ref_iterator { struct ref_iterator base; - struct ref_iterator *iter0, *iter1; + struct ref_iterator *iter0, *iter0_owned; + struct ref_iterator *iter1, *iter1_owned; ref_iterator_select_fn *select; void *cb_data; @@ -179,9 +189,8 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator) iter->select(iter->iter0, iter->iter1, iter->cb_data); if (selection == ITER_SELECT_DONE) { - return ref_iterator_abort(ref_iterator); + return ITER_DONE; } else if (selection == ITER_SELECT_ERROR) { - ref_iterator_abort(ref_iterator); return ITER_ERROR; } @@ -211,10 +220,31 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator) } error: - ref_iterator_abort(ref_iterator); return ITER_ERROR; } +static int merge_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct merge_ref_iterator *iter = + (struct merge_ref_iterator *)ref_iterator; + int ret; + + iter->current = NULL; + iter->iter0 = iter->iter0_owned; + iter->iter1 = iter->iter1_owned; + + ret = ref_iterator_seek(iter->iter0, prefix); + if (ret < 0) + return ret; + + ret = ref_iterator_seek(iter->iter1, prefix); + if (ret < 0) + return ret; + + return 0; +} + static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -227,28 +257,19 @@ static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator, return ref_iterator_peel(*iter->current, peeled); } -static int merge_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void merge_ref_iterator_release(struct ref_iterator *ref_iterator) { struct merge_ref_iterator *iter = (struct merge_ref_iterator *)ref_iterator; - int ok = ITER_DONE; - - if (iter->iter0) { - if (ref_iterator_abort(iter->iter0) != ITER_DONE) - ok = ITER_ERROR; - } - if (iter->iter1) { - if (ref_iterator_abort(iter->iter1) != ITER_DONE) - ok = ITER_ERROR; - } - base_ref_iterator_free(ref_iterator); - return ok; + ref_iterator_free(iter->iter0_owned); + ref_iterator_free(iter->iter1_owned); } static struct ref_iterator_vtable merge_ref_iterator_vtable = { .advance = merge_ref_iterator_advance, + .seek = merge_ref_iterator_seek, .peel = merge_ref_iterator_peel, - .abort = merge_ref_iterator_abort, + .release = merge_ref_iterator_release, }; struct ref_iterator *merge_ref_iterator_begin( @@ -267,8 +288,8 @@ struct ref_iterator *merge_ref_iterator_begin( */ base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable); - iter->iter0 = iter0; - iter->iter1 = iter1; + iter->iter0 = iter->iter0_owned = iter0; + iter->iter1 = iter->iter1_owned = iter1; iter->select = select; iter->cb_data = cb_data; iter->current = NULL; @@ -310,10 +331,10 @@ struct ref_iterator *overlay_ref_iterator_begin( * them. */ if (is_empty_ref_iterator(front)) { - ref_iterator_abort(front); + ref_iterator_free(front); return back; } else if (is_empty_ref_iterator(back)) { - ref_iterator_abort(back); + ref_iterator_free(back); return front; } @@ -350,19 +371,15 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator) while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) { int cmp = compare_prefix(iter->iter0->refname, iter->prefix); - if (cmp < 0) continue; - - if (cmp > 0) { - /* - * As the source iterator is ordered, we - * can stop the iteration as soon as we see a - * refname that comes after the prefix: - */ - ok = ref_iterator_abort(iter->iter0); - break; - } + /* + * As the source iterator is ordered, we + * can stop the iteration as soon as we see a + * refname that comes after the prefix: + */ + if (cmp > 0) + return ITER_DONE; if (iter->trim) { /* @@ -386,12 +403,19 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator) return ITER_OK; } - iter->iter0 = NULL; - if (ref_iterator_abort(ref_iterator) != ITER_DONE) - return ITER_ERROR; return ok; } +static int prefix_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct prefix_ref_iterator *iter = + (struct prefix_ref_iterator *)ref_iterator; + free(iter->prefix); + iter->prefix = xstrdup_or_null(prefix); + return ref_iterator_seek(iter->iter0, prefix); +} + static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -401,23 +425,19 @@ static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator, return ref_iterator_peel(iter->iter0, peeled); } -static int prefix_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void prefix_ref_iterator_release(struct ref_iterator *ref_iterator) { struct prefix_ref_iterator *iter = (struct prefix_ref_iterator *)ref_iterator; - int ok = ITER_DONE; - - if (iter->iter0) - ok = ref_iterator_abort(iter->iter0); + ref_iterator_free(iter->iter0); free(iter->prefix); - base_ref_iterator_free(ref_iterator); - return ok; } static struct ref_iterator_vtable prefix_ref_iterator_vtable = { .advance = prefix_ref_iterator_advance, + .seek = prefix_ref_iterator_seek, .peel = prefix_ref_iterator_peel, - .abort = prefix_ref_iterator_abort, + .release = prefix_ref_iterator_release, }; struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0, @@ -453,20 +473,14 @@ int do_for_each_ref_iterator(struct ref_iterator *iter, current_ref_iter = iter; while ((ok = ref_iterator_advance(iter)) == ITER_OK) { retval = fn(iter->refname, iter->referent, iter->oid, iter->flags, cb_data); - if (retval) { - /* - * If ref_iterator_abort() returns ITER_ERROR, - * we ignore that error in deference to the - * callback function's return value. - */ - ref_iterator_abort(iter); + if (retval) goto out; - } } out: current_ref_iter = old_ref_iter; if (ok == ITER_ERROR) - return -1; + retval = -1; + ref_iterator_free(iter); return retval; } diff --git a/refs/packed-backend.c b/refs/packed-backend.c index a7b6f74b6e..b4289a7d9c 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -4,6 +4,7 @@ #include "../git-compat-util.h" #include "../config.h" #include "../dir.h" +#include "../fsck.h" #include "../gettext.h" #include "../hash.h" #include "../hex.h" @@ -299,14 +300,9 @@ struct snapshot_record { size_t len; }; -static int cmp_packed_ref_records(const void *v1, const void *v2, - void *cb_data) -{ - const struct snapshot *snapshot = cb_data; - const struct snapshot_record *e1 = v1, *e2 = v2; - const char *r1 = e1->start + snapshot_hexsz(snapshot) + 1; - const char *r2 = e2->start + snapshot_hexsz(snapshot) + 1; +static int cmp_packed_refname(const char *r1, const char *r2) +{ while (1) { if (*r1 == '\n') return *r2 == '\n' ? 0 : -1; @@ -321,6 +317,17 @@ static int cmp_packed_ref_records(const void *v1, const void *v2, } } +static int cmp_packed_ref_records(const void *v1, const void *v2, + void *cb_data) +{ + const struct snapshot *snapshot = cb_data; + const struct snapshot_record *e1 = v1, *e2 = v2; + const char *r1 = e1->start + snapshot_hexsz(snapshot) + 1; + const char *r2 = e2->start + snapshot_hexsz(snapshot) + 1; + + return cmp_packed_refname(r1, r2); +} + /* * Compare a snapshot record at `rec` to the specified NUL-terminated * refname. @@ -493,6 +500,21 @@ static void verify_buffer_safe(struct snapshot *snapshot) last_line, eof - last_line); } +/* + * When parsing the "packed-refs" file, we will parse it line by line. + * Because we know the start pointer of the refname and the next + * newline pointer, we could calculate the length of the refname by + * subtracting the two pointers. However, there is a corner case where + * the refname contains corrupted embedded NUL characters. And + * `check_refname_format()` will not catch this when the truncated + * refname is still a valid refname. To prevent this, we need to check + * whether the refname contains the NUL characters. + */ +static int refname_contains_nul(struct strbuf *refname) +{ + return !!memchr(refname->buf, '\0', refname->len); +} + #define SMALL_FILE_SIZE (32*1024) /* @@ -693,7 +715,7 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs) tmp = xmemdupz(snapshot->buf, eol - snapshot->buf); - if (!skip_prefix(tmp, "# pack-refs with:", (const char **)&p)) + if (!skip_prefix(tmp, "# pack-refs with: ", (const char **)&p)) die_invalid_line(refs->path, snapshot->buf, snapshot->eof - snapshot->buf); @@ -819,6 +841,8 @@ struct packed_ref_iterator { struct snapshot *snapshot; + char *prefix; + /* The current position in the snapshot's buffer: */ const char *pos; @@ -841,11 +865,9 @@ struct packed_ref_iterator { }; /* - * Move the iterator to the next record in the snapshot, without - * respect for whether the record is actually required by the current - * iteration. Adjust the fields in `iter` and return `ITER_OK` or - * `ITER_DONE`. This function does not free the iterator in the case - * of `ITER_DONE`. + * Move the iterator to the next record in the snapshot. Adjust the fields in + * `iter` and return `ITER_OK` or `ITER_DONE`. This function does not free the + * iterator in the case of `ITER_DONE`. */ static int next_record(struct packed_ref_iterator *iter) { @@ -894,6 +916,9 @@ static int next_record(struct packed_ref_iterator *iter) strbuf_add(&iter->refname_buf, p, eol - p); iter->base.refname = iter->refname_buf.buf; + if (refname_contains_nul(&iter->refname_buf)) + die("packed refname contains embedded NULL: %s", iter->base.refname); + if (check_refname_format(iter->base.refname, REFNAME_ALLOW_ONELEVEL)) { if (!refname_is_safe(iter->base.refname)) die("packed refname is dangerous: %s", @@ -942,6 +967,9 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator) int ok; while ((ok = next_record(iter)) == ITER_OK) { + const char *refname = iter->base.refname; + const char *prefix = iter->prefix; + if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY && !is_per_worktree_ref(iter->base.refname)) continue; @@ -951,15 +979,41 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator) &iter->oid, iter->flags)) continue; + while (prefix && *prefix) { + if (*refname < *prefix) + BUG("packed-refs backend yielded reference preceding its prefix"); + else if (*refname > *prefix) + return ITER_DONE; + prefix++; + refname++; + } + return ITER_OK; } - if (ref_iterator_abort(ref_iterator) != ITER_DONE) - ok = ITER_ERROR; - return ok; } +static int packed_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct packed_ref_iterator *iter = + (struct packed_ref_iterator *)ref_iterator; + const char *start; + + if (prefix && *prefix) + start = find_reference_location(iter->snapshot, prefix, 0); + else + start = iter->snapshot->start; + + free(iter->prefix); + iter->prefix = xstrdup_or_null(prefix); + iter->pos = start; + iter->eof = iter->snapshot->eof; + + return 0; +} + static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -976,23 +1030,21 @@ static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator, } } -static int packed_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void packed_ref_iterator_release(struct ref_iterator *ref_iterator) { struct packed_ref_iterator *iter = (struct packed_ref_iterator *)ref_iterator; - int ok = ITER_DONE; - strbuf_release(&iter->refname_buf); free(iter->jump); + free(iter->prefix); release_snapshot(iter->snapshot); - base_ref_iterator_free(ref_iterator); - return ok; } static struct ref_iterator_vtable packed_ref_iterator_vtable = { .advance = packed_ref_iterator_advance, + .seek = packed_ref_iterator_seek, .peel = packed_ref_iterator_peel, - .abort = packed_ref_iterator_abort + .release = packed_ref_iterator_release, }; static int jump_list_entry_cmp(const void *va, const void *vb) @@ -1104,7 +1156,6 @@ static struct ref_iterator *packed_ref_iterator_begin( { struct packed_ref_store *refs; struct snapshot *snapshot; - const char *start; struct packed_ref_iterator *iter; struct ref_iterator *ref_iterator; unsigned int required_flags = REF_STORE_READ; @@ -1120,14 +1171,6 @@ static struct ref_iterator *packed_ref_iterator_begin( */ snapshot = get_snapshot(refs); - if (prefix && *prefix) - start = find_reference_location(snapshot, prefix, 0); - else - start = snapshot->start; - - if (start == snapshot->eof) - return empty_ref_iterator_begin(); - CALLOC_ARRAY(iter, 1); ref_iterator = &iter->base; base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable); @@ -1137,19 +1180,15 @@ static struct ref_iterator *packed_ref_iterator_begin( iter->snapshot = snapshot; acquire_snapshot(snapshot); - - iter->pos = start; - iter->eof = snapshot->eof; strbuf_init(&iter->refname_buf, 0); - iter->base.oid = &iter->oid; - iter->repo = ref_store->repo; iter->flags = flags; - if (prefix && *prefix) - /* Stop iteration after we've gone *past* prefix: */ - ref_iterator = prefix_ref_iterator_begin(ref_iterator, prefix, 0); + if (packed_ref_iterator_seek(&iter->base, prefix) < 0) { + ref_iterator_free(&iter->base); + return NULL; + } return ref_iterator; } @@ -1362,8 +1401,10 @@ static int write_with_updates(struct packed_ref_store *refs, */ iter = packed_ref_iterator_begin(&refs->base, "", NULL, DO_FOR_EACH_INCLUDE_BROKEN); - if ((ok = ref_iterator_advance(iter)) != ITER_OK) + if ((ok = ref_iterator_advance(iter)) != ITER_OK) { + ref_iterator_free(iter); iter = NULL; + } i = 0; @@ -1411,8 +1452,10 @@ static int write_with_updates(struct packed_ref_store *refs, * the iterator over the unneeded * value. */ - if ((ok = ref_iterator_advance(iter)) != ITER_OK) + if ((ok = ref_iterator_advance(iter)) != ITER_OK) { + ref_iterator_free(iter); iter = NULL; + } cmp = +1; } else { /* @@ -1449,8 +1492,10 @@ static int write_with_updates(struct packed_ref_store *refs, peel_error ? NULL : &peeled)) goto write_error; - if ((ok = ref_iterator_advance(iter)) != ITER_OK) + if ((ok = ref_iterator_advance(iter)) != ITER_OK) { + ref_iterator_free(iter); iter = NULL; + } } else if (is_null_oid(&update->new_oid)) { /* * The update wants to delete the reference, @@ -1499,9 +1544,7 @@ write_error: get_tempfile_path(refs->tempfile), strerror(errno)); error: - if (iter) - ref_iterator_abort(iter); - + ref_iterator_free(iter); delete_tempfile(&refs->tempfile); return -1; } @@ -1748,15 +1791,329 @@ static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_s return empty_ref_iterator_begin(); } -static int packed_fsck(struct ref_store *ref_store UNUSED, - struct fsck_options *o UNUSED, +static int packed_fsck_ref_next_line(struct fsck_options *o, + unsigned long line_number, const char *start, + const char *eof, const char **eol) +{ + int ret = 0; + + *eol = memchr(start, '\n', eof - start); + if (!*eol) { + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + ret = fsck_report_ref(o, &report, + FSCK_MSG_PACKED_REF_ENTRY_NOT_TERMINATED, + "'%.*s' is not terminated with a newline", + (int)(eof - start), start); + + /* + * There is no newline but we still want to parse it to the end of + * the buffer. + */ + *eol = eof; + strbuf_release(&packed_entry); + } + + return ret; +} + +static int packed_fsck_ref_header(struct fsck_options *o, + const char *start, const char *eol, + unsigned int *sorted) +{ + struct string_list traits = STRING_LIST_INIT_NODUP; + char *tmp_line; + int ret = 0; + char *p; + + tmp_line = xmemdupz(start, eol - start); + if (!skip_prefix(tmp_line, "# pack-refs with: ", (const char **)&p)) { + struct fsck_ref_report report = { 0 }; + report.path = "packed-refs.header"; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_HEADER, + "'%.*s' does not start with '# pack-refs with: '", + (int)(eol - start), start); + goto cleanup; + } + + string_list_split_in_place(&traits, p, " ", -1); + *sorted = unsorted_string_list_has_string(&traits, "sorted"); + +cleanup: + free(tmp_line); + string_list_clear(&traits, 0); + return ret; +} + +static int packed_fsck_ref_peeled_line(struct fsck_options *o, + struct ref_store *ref_store, + unsigned long line_number, + const char *start, const char *eol) +{ + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + struct object_id peeled; + const char *p; + int ret = 0; + + /* + * Skip the '^' and parse the peeled oid. + */ + start++; + if (parse_oid_hex_algop(start, &peeled, &p, ref_store->repo->hash_algo)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "'%.*s' has invalid peeled oid", + (int)(eol - start), start); + goto cleanup; + } + + if (p != eol) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "has trailing garbage after peeled oid '%.*s'", + (int)(eol - p), p); + goto cleanup; + } + +cleanup: + strbuf_release(&packed_entry); + return ret; +} + +static int packed_fsck_ref_main_line(struct fsck_options *o, + struct ref_store *ref_store, + unsigned long line_number, + struct strbuf *refname, + const char *start, const char *eol) +{ + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + struct object_id oid; + const char *p; + int ret = 0; + + if (parse_oid_hex_algop(start, &oid, &p, ref_store->repo->hash_algo)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "'%.*s' has invalid oid", + (int)(eol - start), start); + goto cleanup; + } + + if (p == eol || !isspace(*p)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "has no space after oid '%s' but with '%.*s'", + oid_to_hex(&oid), (int)(eol - p), p); + goto cleanup; + } + + p++; + strbuf_reset(refname); + strbuf_add(refname, p, eol - p); + if (refname_contains_nul(refname)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "refname '%s' contains NULL binaries", + refname->buf); + } + + if (check_refname_format(refname->buf, 0)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_REF_NAME, + "has bad refname '%s'", refname->buf); + } + +cleanup: + strbuf_release(&packed_entry); + return ret; +} + +static int packed_fsck_ref_sorted(struct fsck_options *o, + struct ref_store *ref_store, + const char *start, const char *eof) +{ + size_t hexsz = ref_store->repo->hash_algo->hexsz; + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + struct strbuf refname1 = STRBUF_INIT; + struct strbuf refname2 = STRBUF_INIT; + unsigned long line_number = 1; + const char *former = NULL; + const char *current; + const char *eol; + int ret = 0; + + if (*start == '#') { + eol = memchr(start, '\n', eof - start); + start = eol + 1; + line_number++; + } + + for (; start < eof; line_number++, start = eol + 1) { + eol = memchr(start, '\n', eof - start); + + if (*start == '^') + continue; + + if (!former) { + former = start + hexsz + 1; + continue; + } + + current = start + hexsz + 1; + if (cmp_packed_refname(former, current) >= 0) { + const char *err_fmt = + "refname '%s' is less than previous refname '%s'"; + + eol = memchr(former, '\n', eof - former); + strbuf_add(&refname1, former, eol - former); + eol = memchr(current, '\n', eof - current); + strbuf_add(&refname2, current, eol - current); + + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + ret = fsck_report_ref(o, &report, + FSCK_MSG_PACKED_REF_UNSORTED, + err_fmt, refname2.buf, refname1.buf); + goto cleanup; + } + former = current; + } + +cleanup: + strbuf_release(&packed_entry); + strbuf_release(&refname1); + strbuf_release(&refname2); + return ret; +} + +static int packed_fsck_ref_content(struct fsck_options *o, + struct ref_store *ref_store, + unsigned int *sorted, + const char *start, const char *eof) +{ + struct strbuf refname = STRBUF_INIT; + unsigned long line_number = 1; + const char *eol; + int ret = 0; + + ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol); + if (*start == '#') { + ret |= packed_fsck_ref_header(o, start, eol, sorted); + + start = eol + 1; + line_number++; + } + + while (start < eof) { + ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol); + ret |= packed_fsck_ref_main_line(o, ref_store, line_number, &refname, start, eol); + start = eol + 1; + line_number++; + if (start < eof && *start == '^') { + ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol); + ret |= packed_fsck_ref_peeled_line(o, ref_store, line_number, + start, eol); + start = eol + 1; + line_number++; + } + } + + strbuf_release(&refname); + return ret; +} + +static int packed_fsck(struct ref_store *ref_store, + struct fsck_options *o, struct worktree *wt) { + struct packed_ref_store *refs = packed_downcast(ref_store, + REF_STORE_READ, "fsck"); + struct strbuf packed_ref_content = STRBUF_INIT; + unsigned int sorted = 0; + struct stat st; + int ret = 0; + int fd = -1; if (!is_main_worktree(wt)) - return 0; + goto cleanup; - return 0; + if (o->verbose) + fprintf_ln(stderr, "Checking packed-refs file %s", refs->path); + + fd = open_nofollow(refs->path, O_RDONLY); + if (fd < 0) { + /* + * If the packed-refs file doesn't exist, there's nothing + * to check. + */ + if (errno == ENOENT) + goto cleanup; + + if (errno == ELOOP) { + struct fsck_ref_report report = { 0 }; + report.path = "packed-refs"; + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_REF_FILETYPE, + "not a regular file but a symlink"); + goto cleanup; + } + + ret = error_errno(_("unable to open '%s'"), refs->path); + goto cleanup; + } else if (fstat(fd, &st) < 0) { + ret = error_errno(_("unable to stat '%s'"), refs->path); + goto cleanup; + } else if (!S_ISREG(st.st_mode)) { + struct fsck_ref_report report = { 0 }; + report.path = "packed-refs"; + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_REF_FILETYPE, + "not a regular file"); + goto cleanup; + } + + if (strbuf_read(&packed_ref_content, fd, 0) < 0) { + ret = error_errno(_("unable to read '%s'"), refs->path); + goto cleanup; + } + + ret = packed_fsck_ref_content(o, ref_store, &sorted, packed_ref_content.buf, + packed_ref_content.buf + packed_ref_content.len); + if (!ret && sorted) + ret = packed_fsck_ref_sorted(o, ref_store, packed_ref_content.buf, + packed_ref_content.buf + packed_ref_content.len); + +cleanup: + if (fd >= 0) + close(fd); + strbuf_release(&packed_ref_content); + return ret; } struct ref_storage_be refs_be_packed = { diff --git a/refs/ref-cache.c b/refs/ref-cache.c index 02f09e4df8..c1f1bab1d5 100644 --- a/refs/ref-cache.c +++ b/refs/ref-cache.c @@ -362,9 +362,7 @@ struct cache_ref_iterator { struct ref_iterator base; /* - * The number of levels currently on the stack. This is always - * at least 1, because when it becomes zero the iteration is - * ended and this struct is freed. + * The number of levels currently on the stack. */ size_t levels_nr; @@ -376,7 +374,7 @@ struct cache_ref_iterator { * The prefix is matched textually, without regard for path * component boundaries. */ - const char *prefix; + char *prefix; /* * A stack of levels. levels[0] is the uppermost level that is @@ -389,6 +387,9 @@ struct cache_ref_iterator { struct cache_ref_iterator_level *levels; struct repository *repo; + struct ref_cache *cache; + + int prime_dir; }; static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator) @@ -396,6 +397,9 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator) struct cache_ref_iterator *iter = (struct cache_ref_iterator *)ref_iterator; + if (!iter->levels_nr) + return ITER_DONE; + while (1) { struct cache_ref_iterator_level *level = &iter->levels[iter->levels_nr - 1]; @@ -409,7 +413,7 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator) if (++level->index == level->dir->nr) { /* This level is exhausted; pop up a level */ if (--iter->levels_nr == 0) - return ref_iterator_abort(ref_iterator); + return ITER_DONE; continue; } @@ -444,6 +448,41 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator) } } +static int cache_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct cache_ref_iterator *iter = + (struct cache_ref_iterator *)ref_iterator; + struct cache_ref_iterator_level *level; + struct ref_dir *dir; + + dir = get_ref_dir(iter->cache->root); + if (prefix && *prefix) + dir = find_containing_dir(dir, prefix); + if (!dir) { + iter->levels_nr = 0; + return 0; + } + + if (iter->prime_dir) + prime_ref_dir(dir, prefix); + iter->levels_nr = 1; + level = &iter->levels[0]; + level->index = -1; + level->dir = dir; + + if (prefix && *prefix) { + free(iter->prefix); + iter->prefix = xstrdup(prefix); + level->prefix_state = PREFIX_WITHIN_DIR; + } else { + FREE_AND_NULL(iter->prefix); + level->prefix_state = PREFIX_CONTAINS_DIR; + } + + return 0; +} + static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -452,21 +491,19 @@ static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator, return peel_object(iter->repo, ref_iterator->oid, peeled) ? -1 : 0; } -static int cache_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void cache_ref_iterator_release(struct ref_iterator *ref_iterator) { struct cache_ref_iterator *iter = (struct cache_ref_iterator *)ref_iterator; - - free((char *)iter->prefix); + free(iter->prefix); free(iter->levels); - base_ref_iterator_free(ref_iterator); - return ITER_DONE; } static struct ref_iterator_vtable cache_ref_iterator_vtable = { .advance = cache_ref_iterator_advance, + .seek = cache_ref_iterator_seek, .peel = cache_ref_iterator_peel, - .abort = cache_ref_iterator_abort + .release = cache_ref_iterator_release, }; struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache, @@ -474,39 +511,22 @@ struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache, struct repository *repo, int prime_dir) { - struct ref_dir *dir; struct cache_ref_iterator *iter; struct ref_iterator *ref_iterator; - struct cache_ref_iterator_level *level; - - dir = get_ref_dir(cache->root); - if (prefix && *prefix) - dir = find_containing_dir(dir, prefix); - if (!dir) - /* There's nothing to iterate over. */ - return empty_ref_iterator_begin(); - - if (prime_dir) - prime_ref_dir(dir, prefix); CALLOC_ARRAY(iter, 1); ref_iterator = &iter->base; base_ref_iterator_init(ref_iterator, &cache_ref_iterator_vtable); ALLOC_GROW(iter->levels, 10, iter->levels_alloc); - iter->levels_nr = 1; - level = &iter->levels[0]; - level->index = -1; - level->dir = dir; + iter->repo = repo; + iter->cache = cache; + iter->prime_dir = prime_dir; - if (prefix && *prefix) { - iter->prefix = xstrdup(prefix); - level->prefix_state = PREFIX_WITHIN_DIR; - } else { - level->prefix_state = PREFIX_CONTAINS_DIR; + if (cache_ref_iterator_seek(&iter->base, prefix) < 0) { + ref_iterator_free(&iter->base); + return NULL; } - iter->repo = repo; - return ref_iterator; } diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 16550862d3..e5862757a7 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -120,7 +120,7 @@ struct ref_update { * when migrating reflogs and we want to ensure we carry over the * same order. */ - unsigned int index; + uint64_t index; /* * If this ref_update was split off of a symref update via @@ -203,6 +203,7 @@ struct ref_transaction { enum ref_transaction_state state; void *backend_data; unsigned int flags; + uint64_t max_index; }; /* @@ -272,11 +273,11 @@ enum do_for_each_ref_flags { * the next reference and returns ITER_OK. The data pointed at by * refname and oid belong to the iterator; if you want to retain them * after calling ref_iterator_advance() again or calling - * ref_iterator_abort(), you must make a copy. When the iteration has + * ref_iterator_free(), you must make a copy. When the iteration has * been exhausted, ref_iterator_advance() releases any resources * associated with the iteration, frees the ref_iterator object, and * returns ITER_DONE. If you want to abort the iteration early, call - * ref_iterator_abort(), which also frees the ref_iterator object and + * ref_iterator_free(), which also frees the ref_iterator object and * any associated resources. If there was an internal error advancing * to the next entry, ref_iterator_advance() aborts the iteration, * frees the ref_iterator, and returns ITER_ERROR. @@ -292,7 +293,7 @@ enum do_for_each_ref_flags { * * while ((ok = ref_iterator_advance(iter)) == ITER_OK) { * if (want_to_stop_iteration()) { - * ok = ref_iterator_abort(iter); + * ok = ITER_DONE; * break; * } * @@ -306,6 +307,7 @@ enum do_for_each_ref_flags { * * if (ok != ITER_DONE) * handle_error(); + * ref_iterator_free(iter); */ struct ref_iterator { struct ref_iterator_vtable *vtable; @@ -326,18 +328,30 @@ struct ref_iterator { int ref_iterator_advance(struct ref_iterator *ref_iterator); /* + * Seek the iterator to the first reference with the given prefix. + * The prefix is matched as a literal string, without regard for path + * separators. If prefix is NULL or the empty string, seek the iterator to the + * first reference again. + * + * This function is expected to behave as if a new ref iterator with the same + * prefix had been created, but allows reuse of iterators and thus may allow + * the backend to optimize. Parameters other than the prefix that have been + * passed when creating the iterator will remain unchanged. + * + * Returns 0 on success, a negative error code otherwise. + */ +int ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix); + +/* * If possible, peel the reference currently being viewed by the * iterator. Return 0 on success. */ int ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled); -/* - * End the iteration before it has been exhausted, freeing the - * reference iterator and any associated resources and returning - * ITER_DONE. If the abort itself failed, return ITER_ERROR. - */ -int ref_iterator_abort(struct ref_iterator *ref_iterator); +/* Free the reference iterator and any associated resources. */ +void ref_iterator_free(struct ref_iterator *ref_iterator); /* * An iterator over nothing (its first ref_iterator_advance() call @@ -437,13 +451,6 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0, void base_ref_iterator_init(struct ref_iterator *iter, struct ref_iterator_vtable *vtable); -/* - * Base class destructor for ref_iterators. Destroy the ref_iterator - * part of iter and shallow-free the object. This is meant to be - * called only by the destructors of derived classes. - */ -void base_ref_iterator_free(struct ref_iterator *iter); - /* Virtual function declarations for ref_iterators: */ /* @@ -455,6 +462,13 @@ void base_ref_iterator_free(struct ref_iterator *iter); typedef int ref_iterator_advance_fn(struct ref_iterator *ref_iterator); /* + * Seek the iterator to the first reference matching the given prefix. Should + * behave the same as if a new iterator was created with the same prefix. + */ +typedef int ref_iterator_seek_fn(struct ref_iterator *ref_iterator, + const char *prefix); + +/* * Peels the current ref, returning 0 for success or -1 for failure. */ typedef int ref_iterator_peel_fn(struct ref_iterator *ref_iterator, @@ -462,15 +476,15 @@ typedef int ref_iterator_peel_fn(struct ref_iterator *ref_iterator, /* * Implementations of this function should free any resources specific - * to the derived class, then call base_ref_iterator_free() to clean - * up and free the ref_iterator object. + * to the derived class. */ -typedef int ref_iterator_abort_fn(struct ref_iterator *ref_iterator); +typedef void ref_iterator_release_fn(struct ref_iterator *ref_iterator); struct ref_iterator_vtable { ref_iterator_advance_fn *advance; + ref_iterator_seek_fn *seek; ref_iterator_peel_fn *peel; - ref_iterator_abort_fn *abort; + ref_iterator_release_fn *release; }; /* diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index 00d95a9a2f..ae434cd248 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -380,7 +380,7 @@ static struct ref_store *reftable_be_init(struct repository *repo, default: BUG("unknown hash algorithm %d", repo->hash_algo->format_id); } - refs->write_options.default_permissions = calc_shared_perm(0666 & ~mask); + refs->write_options.default_permissions = calc_shared_perm(the_repository, 0666 & ~mask); refs->write_options.disable_auto_compact = !git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1); refs->write_options.lock_timeout_ms = 100; @@ -470,21 +470,21 @@ static int reftable_be_create_on_disk(struct ref_store *ref_store, struct strbuf sb = STRBUF_INIT; strbuf_addf(&sb, "%s/reftable", refs->base.gitdir); - safe_create_dir(sb.buf, 1); + safe_create_dir(the_repository, sb.buf, 1); strbuf_reset(&sb); strbuf_addf(&sb, "%s/HEAD", refs->base.gitdir); write_file(sb.buf, "ref: refs/heads/.invalid"); - adjust_shared_perm(sb.buf); + adjust_shared_perm(the_repository, sb.buf); strbuf_reset(&sb); strbuf_addf(&sb, "%s/refs", refs->base.gitdir); - safe_create_dir(sb.buf, 1); + safe_create_dir(the_repository, sb.buf, 1); strbuf_reset(&sb); strbuf_addf(&sb, "%s/refs/heads", refs->base.gitdir); write_file(sb.buf, "this repository uses the reftable format"); - adjust_shared_perm(sb.buf); + adjust_shared_perm(the_repository, sb.buf); strbuf_release(&sb); return 0; @@ -547,7 +547,7 @@ struct reftable_ref_iterator { struct reftable_ref_record ref; struct object_id oid; - const char *prefix; + char *prefix; size_t prefix_len; char **exclude_patterns; size_t exclude_patterns_index; @@ -711,20 +711,27 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator) break; } - if (iter->err > 0) { - if (ref_iterator_abort(ref_iterator) != ITER_DONE) - return ITER_ERROR; + if (iter->err > 0) return ITER_DONE; - } - - if (iter->err < 0) { - ref_iterator_abort(ref_iterator); + if (iter->err < 0) return ITER_ERROR; - } - return ITER_OK; } +static int reftable_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct reftable_ref_iterator *iter = + (struct reftable_ref_iterator *)ref_iterator; + + free(iter->prefix); + iter->prefix = xstrdup_or_null(prefix); + iter->prefix_len = prefix ? strlen(prefix) : 0; + iter->err = reftable_iterator_seek_ref(&iter->iter, prefix); + + return iter->err; +} + static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -740,7 +747,7 @@ static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator, return -1; } -static int reftable_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void reftable_ref_iterator_release(struct ref_iterator *ref_iterator) { struct reftable_ref_iterator *iter = (struct reftable_ref_iterator *)ref_iterator; @@ -751,14 +758,14 @@ static int reftable_ref_iterator_abort(struct ref_iterator *ref_iterator) free(iter->exclude_patterns[i]); free(iter->exclude_patterns); } - free(iter); - return ITER_DONE; + free(iter->prefix); } static struct ref_iterator_vtable reftable_ref_iterator_vtable = { .advance = reftable_ref_iterator_advance, + .seek = reftable_ref_iterator_seek, .peel = reftable_ref_iterator_peel, - .abort = reftable_ref_iterator_abort + .release = reftable_ref_iterator_release, }; static int qsort_strcmp(const void *va, const void *vb) @@ -815,8 +822,6 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_ iter = xcalloc(1, sizeof(*iter)); base_ref_iterator_init(&iter->base, &reftable_ref_iterator_vtable); - iter->prefix = prefix; - iter->prefix_len = prefix ? strlen(prefix) : 0; iter->base.oid = &iter->oid; iter->flags = flags; iter->refs = refs; @@ -830,8 +835,11 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_ if (ret) goto done; - reftable_stack_init_ref_iterator(stack, &iter->iter); - ret = reftable_iterator_seek_ref(&iter->iter, prefix); + ret = reftable_stack_init_ref_iterator(stack, &iter->iter); + if (ret) + goto done; + + ret = reftable_ref_iterator_seek(&iter->base, prefix); if (ret) goto done; @@ -942,6 +950,7 @@ struct write_transaction_table_arg { size_t updates_nr; size_t updates_alloc; size_t updates_expected; + uint64_t max_index; }; struct reftable_transaction_data { @@ -1019,6 +1028,7 @@ static int prepare_transaction_update(struct write_transaction_table_arg **out, arg->updates_nr = 0; arg->updates_alloc = 0; arg->updates_expected = 0; + arg->max_index = 0; } arg->updates_expected++; @@ -1067,6 +1077,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, reftable_be_downcast(ref_store, REF_STORE_WRITE|REF_STORE_MAIN, "ref_transaction_prepare"); struct strbuf referent = STRBUF_INIT, head_referent = STRBUF_INIT; struct string_list affected_refnames = STRING_LIST_INIT_NODUP; + struct string_list refnames_to_check = STRING_LIST_INIT_NODUP; struct reftable_transaction_data *tx_data = NULL; struct reftable_backend *be; struct object_id head_oid; @@ -1222,12 +1233,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, * can output a proper error message instead of failing * at a later point. */ - ret = refs_verify_refname_available(ref_store, u->refname, - &affected_refnames, NULL, - transaction->flags & REF_TRANSACTION_FLAG_INITIAL, - err); - if (ret < 0) - goto done; + string_list_append(&refnames_to_check, u->refname); /* * There is no need to write the reference deletion @@ -1377,6 +1383,12 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, } } + ret = refs_verify_refnames_available(ref_store, &refnames_to_check, &affected_refnames, NULL, + transaction->flags & REF_TRANSACTION_FLAG_INITIAL, + err); + if (ret < 0) + goto done; + transaction->backend_data = tx_data; transaction->state = REF_TRANSACTION_PREPARED; @@ -1392,6 +1404,7 @@ done: string_list_clear(&affected_refnames, 0); strbuf_release(&referent); strbuf_release(&head_referent); + string_list_clear(&refnames_to_check, 0); return ret; } @@ -1428,7 +1441,6 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data struct reftable_log_record *logs = NULL; struct ident_split committer_ident = {0}; size_t logs_nr = 0, logs_alloc = 0, i; - uint64_t max_update_index = ts; const char *committer_info; int ret = 0; @@ -1438,7 +1450,14 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data QSORT(arg->updates, arg->updates_nr, transaction_update_cmp); - reftable_writer_set_limits(writer, ts, ts); + /* + * During reflog migration, we add indexes for a single reflog with + * multiple entries. Each entry will contain a different update_index, + * so set the limits accordingly. + */ + ret = reftable_writer_set_limits(writer, ts, ts + arg->max_index); + if (ret < 0) + goto done; for (i = 0; i < arg->updates_nr; i++) { struct reftable_transaction_update *tx_update = &arg->updates[i]; @@ -1540,12 +1559,6 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data */ log->update_index = ts + u->index; - /* - * Note the max update_index so the limit can be set later on. - */ - if (log->update_index > max_update_index) - max_update_index = log->update_index; - log->refname = xstrdup(u->refname); memcpy(log->value.update.new_hash, u->new_oid.hash, GIT_MAX_RAWSZ); @@ -1609,8 +1622,6 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data * and log blocks. */ if (logs) { - reftable_writer_set_limits(writer, ts, max_update_index); - ret = reftable_writer_add_logs(writer, logs, logs_nr); if (ret < 0) goto done; @@ -1632,6 +1643,8 @@ static int reftable_be_transaction_finish(struct ref_store *ref_store UNUSED, int ret = 0; for (size_t i = 0; i < tx_data->args_nr; i++) { + tx_data->args[i].max_index = transaction->max_index; + ret = reftable_addition_add(tx_data->args[i].addition, write_transaction_table, &tx_data->args[i]); if (ret < 0) @@ -1766,7 +1779,9 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data) deletion_ts = creation_ts = reftable_stack_next_update_index(arg->be->stack); if (arg->delete_old) creation_ts++; - reftable_writer_set_limits(writer, deletion_ts, creation_ts); + ret = reftable_writer_set_limits(writer, deletion_ts, creation_ts); + if (ret < 0) + goto done; /* * Add the new reference. If this is a rename then we also delete the @@ -2013,20 +2028,20 @@ static int reftable_reflog_iterator_advance(struct ref_iterator *ref_iterator) break; } - if (iter->err > 0) { - if (ref_iterator_abort(ref_iterator) != ITER_DONE) - return ITER_ERROR; + if (iter->err > 0) return ITER_DONE; - } - - if (iter->err < 0) { - ref_iterator_abort(ref_iterator); + if (iter->err < 0) return ITER_ERROR; - } - return ITER_OK; } +static int reftable_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSED, + const char *prefix UNUSED) +{ + BUG("reftable reflog iterator cannot be seeked"); + return -1; +} + static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED, struct object_id *peeled UNUSED) { @@ -2034,21 +2049,20 @@ static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSE return -1; } -static int reftable_reflog_iterator_abort(struct ref_iterator *ref_iterator) +static void reftable_reflog_iterator_release(struct ref_iterator *ref_iterator) { struct reftable_reflog_iterator *iter = (struct reftable_reflog_iterator *)ref_iterator; reftable_log_record_release(&iter->log); reftable_iterator_destroy(&iter->iter); strbuf_release(&iter->last_name); - free(iter); - return ITER_DONE; } static struct ref_iterator_vtable reftable_reflog_iterator_vtable = { .advance = reftable_reflog_iterator_advance, + .seek = reftable_reflog_iterator_seek, .peel = reftable_reflog_iterator_peel, - .abort = reftable_reflog_iterator_abort + .release = reftable_reflog_iterator_release, }; static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftable_ref_store *refs, @@ -2298,7 +2312,9 @@ static int write_reflog_existence_table(struct reftable_writer *writer, if (ret <= 0) goto done; - reftable_writer_set_limits(writer, ts, ts); + ret = reftable_writer_set_limits(writer, ts, ts); + if (ret < 0) + goto done; /* * The existence entry has both old and new object ID set to the @@ -2357,7 +2373,9 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da uint64_t ts = reftable_stack_next_update_index(arg->stack); int ret; - reftable_writer_set_limits(writer, ts, ts); + ret = reftable_writer_set_limits(writer, ts, ts); + if (ret < 0) + goto out; ret = reftable_stack_init_log_iterator(arg->stack, &it); if (ret < 0) @@ -2434,7 +2452,9 @@ static int write_reflog_expiry_table(struct reftable_writer *writer, void *cb_da if (arg->records[i].value_type == REFTABLE_LOG_UPDATE) live_records++; - reftable_writer_set_limits(writer, ts, ts); + ret = reftable_writer_set_limits(writer, ts, ts); + if (ret < 0) + return ret; if (!is_null_oid(&arg->update_oid)) { struct reftable_ref_record ref = {0}; @@ -5,9 +5,11 @@ #include "gettext.h" #include "hash.h" #include "hex.h" +#include "string-list.h" #include "strvec.h" #include "refs.h" #include "refspec.h" +#include "remote.h" #include "strbuf.h" /* @@ -236,16 +238,6 @@ int valid_fetch_refspec(const char *fetch_refspec_str) return ret; } -int valid_remote_name(const char *name) -{ - int result; - struct strbuf refspec = STRBUF_INIT; - strbuf_addf(&refspec, "refs/heads/test:refs/remotes/%s/test", name); - result = valid_fetch_refspec(refspec.buf); - strbuf_release(&refspec); - return result; -} - void refspec_ref_prefixes(const struct refspec *rs, struct strvec *ref_prefixes) { @@ -254,14 +246,24 @@ void refspec_ref_prefixes(const struct refspec *rs, const struct refspec_item *item = &rs->items[i]; const char *prefix = NULL; - if (item->exact_sha1 || item->negative) + if (item->negative) continue; - if (rs->fetch == REFSPEC_FETCH) - prefix = item->src; - else if (item->dst) - prefix = item->dst; - else if (item->src && !item->exact_sha1) + + if (rs->fetch == REFSPEC_FETCH) { + if (item->exact_sha1) + continue; prefix = item->src; + } else { + /* + * Pushes can have an explicit destination like + * "foo:bar", or can implicitly use the src for both + * ("foo" is the same as "foo:foo"). + */ + if (item->dst) + prefix = item->dst; + else if (item->src && !item->exact_sha1) + prefix = item->src; + } if (!prefix) continue; @@ -276,3 +278,204 @@ void refspec_ref_prefixes(const struct refspec *rs, } } } + +int match_refname_with_pattern(const char *pattern, const char *refname, + const char *replacement, char **result) +{ + const char *kstar = strchr(pattern, '*'); + size_t klen; + size_t ksuffixlen; + size_t namelen; + int ret; + if (!kstar) + die(_("pattern '%s' has no '*'"), pattern); + klen = kstar - pattern; + ksuffixlen = strlen(kstar + 1); + namelen = strlen(refname); + ret = !strncmp(refname, pattern, klen) && namelen >= klen + ksuffixlen && + !memcmp(refname + namelen - ksuffixlen, kstar + 1, ksuffixlen); + if (ret && replacement) { + struct strbuf sb = STRBUF_INIT; + const char *vstar = strchr(replacement, '*'); + if (!vstar) + die(_("replacement '%s' has no '*'"), replacement); + strbuf_add(&sb, replacement, vstar - replacement); + strbuf_add(&sb, refname + klen, namelen - klen - ksuffixlen); + strbuf_addstr(&sb, vstar + 1); + *result = strbuf_detach(&sb, NULL); + } + return ret; +} + +static int refspec_match(const struct refspec_item *refspec, + const char *name) +{ + if (refspec->pattern) + return match_refname_with_pattern(refspec->src, name, NULL, NULL); + + return !strcmp(refspec->src, name); +} + +int refname_matches_negative_refspec_item(const char *refname, struct refspec *rs) +{ + int i; + + for (i = 0; i < rs->nr; i++) { + if (rs->items[i].negative && refspec_match(&rs->items[i], refname)) + return 1; + } + return 0; +} + +static int refspec_find_negative_match(struct refspec *rs, struct refspec_item *query) +{ + int i, matched_negative = 0; + int find_src = !query->src; + struct string_list reversed = STRING_LIST_INIT_DUP; + const char *needle = find_src ? query->dst : query->src; + + /* + * Check whether the queried ref matches any negative refpsec. If so, + * then we should ultimately treat this as not matching the query at + * all. + * + * Note that negative refspecs always match the source, but the query + * item uses the destination. To handle this, we apply pattern + * refspecs in reverse to figure out if the query source matches any + * of the negative refspecs. + * + * The first loop finds and expands all positive refspecs + * matched by the queried ref. + * + * The second loop checks if any of the results of the first loop + * match any negative refspec. + */ + for (i = 0; i < rs->nr; i++) { + struct refspec_item *refspec = &rs->items[i]; + char *expn_name; + + if (refspec->negative) + continue; + + /* Note the reversal of src and dst */ + if (refspec->pattern) { + const char *key = refspec->dst ? refspec->dst : refspec->src; + const char *value = refspec->src; + + if (match_refname_with_pattern(key, needle, value, &expn_name)) + string_list_append_nodup(&reversed, expn_name); + } else if (refspec->matching) { + /* For the special matching refspec, any query should match */ + string_list_append(&reversed, needle); + } else if (!refspec->src) { + BUG("refspec->src should not be null here"); + } else if (!strcmp(needle, refspec->src)) { + string_list_append(&reversed, refspec->src); + } + } + + for (i = 0; !matched_negative && i < reversed.nr; i++) { + if (refname_matches_negative_refspec_item(reversed.items[i].string, rs)) + matched_negative = 1; + } + + string_list_clear(&reversed, 0); + + return matched_negative; +} + +void refspec_find_all_matches(struct refspec *rs, + struct refspec_item *query, + struct string_list *results) +{ + int i; + int find_src = !query->src; + + if (find_src && !query->dst) + BUG("refspec_find_all_matches: need either src or dst"); + + if (refspec_find_negative_match(rs, query)) + return; + + for (i = 0; i < rs->nr; i++) { + struct refspec_item *refspec = &rs->items[i]; + const char *key = find_src ? refspec->dst : refspec->src; + const char *value = find_src ? refspec->src : refspec->dst; + const char *needle = find_src ? query->dst : query->src; + char **result = find_src ? &query->src : &query->dst; + + if (!refspec->dst || refspec->negative) + continue; + if (refspec->pattern) { + if (match_refname_with_pattern(key, needle, value, result)) + string_list_append_nodup(results, *result); + } else if (!strcmp(needle, key)) { + string_list_append(results, value); + } + } +} + +int refspec_find_match(struct refspec *rs, struct refspec_item *query) +{ + int i; + int find_src = !query->src; + const char *needle = find_src ? query->dst : query->src; + char **result = find_src ? &query->src : &query->dst; + + if (find_src && !query->dst) + BUG("refspec_find_match: need either src or dst"); + + if (refspec_find_negative_match(rs, query)) + return -1; + + for (i = 0; i < rs->nr; i++) { + struct refspec_item *refspec = &rs->items[i]; + const char *key = find_src ? refspec->dst : refspec->src; + const char *value = find_src ? refspec->src : refspec->dst; + + if (!refspec->dst || refspec->negative) + continue; + if (refspec->pattern) { + if (match_refname_with_pattern(key, needle, value, result)) { + query->force = refspec->force; + return 0; + } + } else if (!strcmp(needle, key)) { + *result = xstrdup(value); + query->force = refspec->force; + return 0; + } + } + return -1; +} + +struct ref *apply_negative_refspecs(struct ref *ref_map, struct refspec *rs) +{ + struct ref **tail; + + for (tail = &ref_map; *tail; ) { + struct ref *ref = *tail; + + if (refname_matches_negative_refspec_item(ref->name, rs)) { + *tail = ref->next; + free(ref->peer_ref); + free(ref); + } else + tail = &ref->next; + } + + return ref_map; +} + +char *apply_refspecs(struct refspec *rs, const char *name) +{ + struct refspec_item query; + + memset(&query, 0, sizeof(struct refspec_item)); + query.src = (char *)name; + + if (refspec_find_match(rs, &query)) + return NULL; + + return query.dst; +} @@ -30,6 +30,8 @@ struct refspec_item { char *raw; }; +struct string_list; + #define REFSPEC_FETCH 1 #define REFSPEC_PUSH 0 @@ -61,7 +63,6 @@ void refspec_appendn(struct refspec *rs, const char **refspecs, int nr); void refspec_clear(struct refspec *rs); int valid_fetch_refspec(const char *refspec); -int valid_remote_name(const char *name); struct strvec; /* @@ -71,4 +72,40 @@ struct strvec; void refspec_ref_prefixes(const struct refspec *rs, struct strvec *ref_prefixes); +int refname_matches_negative_refspec_item(const char *refname, struct refspec *rs); + +/* + * Checks if a refname matches a globbing refspec pattern. + * If replacement is provided, computes the corresponding mapped refname. + * Returns 1 if refname matches pattern, 0 otherwise. + */ +int match_refname_with_pattern(const char *pattern, const char *refname, + const char *replacement, char **result); + +/* + * Queries a refspec for a match and updates the query item. + * Returns 0 on success, -1 if no match is found or negative refspec matches. + */ +int refspec_find_match(struct refspec *rs, struct refspec_item *query); + +/* + * Queries a refspec for all matches and appends results to the provided string + * list. + */ +void refspec_find_all_matches(struct refspec *rs, + struct refspec_item *query, + struct string_list *results); + +/* + * Remove all entries in the input list which match any negative refspec in + * the refspec list. + */ +struct ref *apply_negative_refspecs(struct ref *ref_map, struct refspec *rs); + +/* + * Search for a refspec that matches the given name and return the + * corresponding destination (dst) if a match is found, NULL otherwise. + */ +char *apply_refspecs(struct refspec *rs, const char *name); + #endif /* REFSPEC_H */ diff --git a/reftable/basics.c b/reftable/basics.c index fe2b83ff83..3b5ea27bbd 100644 --- a/reftable/basics.c +++ b/reftable/basics.c @@ -263,18 +263,16 @@ int names_equal(const char **a, const char **b) return a[i] == b[i]; } -int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b) +size_t common_prefix_size(struct reftable_buf *a, struct reftable_buf *b) { - int p = 0; - for (; p < a->len && p < b->len; p++) { + size_t p = 0; + for (; p < a->len && p < b->len; p++) if (a->buf[p] != b->buf[p]) break; - } - return p; } -int hash_size(enum reftable_hash id) +uint32_t hash_size(enum reftable_hash id) { if (!id) return REFTABLE_HASH_SIZE_SHA1; diff --git a/reftable/basics.h b/reftable/basics.h index 4bf71b0954..a2a010a0e1 100644 --- a/reftable/basics.h +++ b/reftable/basics.h @@ -169,9 +169,9 @@ static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize, #endif /* Find the longest shared prefix size of `a` and `b` */ -int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b); +size_t common_prefix_size(struct reftable_buf *a, struct reftable_buf *b); -int hash_size(enum reftable_hash id); +uint32_t hash_size(enum reftable_hash id); /* * Format IDs that identify the hash function used by a reftable. Note that diff --git a/reftable/block.c b/reftable/block.c index 9858bbc7c5..b14a8f1259 100644 --- a/reftable/block.c +++ b/reftable/block.c @@ -13,9 +13,8 @@ https://developers.google.com/open-source/licenses/bsd #include "record.h" #include "reftable-error.h" #include "system.h" -#include <zlib.h> -int header_size(int version) +size_t header_size(int version) { switch (version) { case 1: @@ -26,7 +25,7 @@ int header_size(int version) abort(); } -int footer_size(int version) +size_t footer_size(int version) { switch (version) { case 1: @@ -40,16 +39,15 @@ int footer_size(int version) static int block_writer_register_restart(struct block_writer *w, int n, int is_restart, struct reftable_buf *key) { - int rlen, err; + uint32_t rlen; + int err; rlen = w->restart_len; - if (rlen >= MAX_RESTARTS) { + if (rlen >= MAX_RESTARTS) is_restart = 0; - } - if (is_restart) { + if (is_restart) rlen++; - } if (2 + 3 * rlen + n > w->block_size - w->next) return -1; if (is_restart) { @@ -72,7 +70,7 @@ static int block_writer_register_restart(struct block_writer *w, int n, } int block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *block, - uint32_t block_size, uint32_t header_off, int hash_size) + uint32_t block_size, uint32_t header_off, uint32_t hash_size) { bw->block = block; bw->hash_size = hash_size; @@ -148,8 +146,7 @@ done: int block_writer_finish(struct block_writer *w) { - int i; - for (i = 0; i < w->restart_len; i++) { + for (uint32_t i = 0; i < w->restart_len; i++) { put_be24(w->block + w->next, w->restarts[i]); w->next += 3; } @@ -214,7 +211,7 @@ int block_writer_finish(struct block_writer *w) int block_reader_init(struct block_reader *br, struct reftable_block *block, uint32_t header_off, uint32_t table_block_size, - int hash_size) + uint32_t hash_size) { uint32_t full_block_size = table_block_size; uint8_t typ = block->data[header_off]; diff --git a/reftable/block.h b/reftable/block.h index 0431e8591f..bef2b8a4c5 100644 --- a/reftable/block.h +++ b/reftable/block.h @@ -30,7 +30,7 @@ struct block_writer { /* How often to restart keys. */ uint16_t restart_interval; - int hash_size; + uint32_t hash_size; /* Offset of next uint8_t to write. */ uint32_t next; @@ -48,7 +48,7 @@ struct block_writer { * initializes the blockwriter to write `typ` entries, using `block` as temporary * storage. `block` is not owned by the block_writer. */ int block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *block, - uint32_t block_size, uint32_t header_off, int hash_size); + uint32_t block_size, uint32_t header_off, uint32_t hash_size); /* returns the block type (eg. 'r' for ref records. */ uint8_t block_writer_type(struct block_writer *bw); @@ -72,7 +72,7 @@ struct block_reader { /* the memory block */ struct reftable_block block; - int hash_size; + uint32_t hash_size; /* Uncompressed data for log entries. */ z_stream *zstream; @@ -92,7 +92,7 @@ struct block_reader { /* initializes a block reader. */ int block_reader_init(struct block_reader *br, struct reftable_block *bl, uint32_t header_off, uint32_t table_block_size, - int hash_size); + uint32_t hash_size); void block_reader_release(struct block_reader *br); @@ -108,7 +108,7 @@ struct block_iter { uint32_t next_off; const unsigned char *block; size_t block_len; - int hash_size; + uint32_t hash_size; /* key for last entry we read. */ struct reftable_buf last_key; @@ -137,10 +137,10 @@ void block_iter_reset(struct block_iter *it); void block_iter_close(struct block_iter *it); /* size of file header, depending on format version */ -int header_size(int version); +size_t header_size(int version); /* size of file footer, depending on format version */ -int footer_size(int version); +size_t footer_size(int version); /* returns a block to its source. */ void reftable_block_done(struct reftable_block *ret); diff --git a/reftable/blocksource.c b/reftable/blocksource.c index 52e0915a67..bba4a45b98 100644 --- a/reftable/blocksource.c +++ b/reftable/blocksource.c @@ -24,8 +24,8 @@ static void reftable_buf_close(void *b UNUSED) { } -static int reftable_buf_read_block(void *v, struct reftable_block *dest, - uint64_t off, uint32_t size) +static ssize_t reftable_buf_read_block(void *v, struct reftable_block *dest, + uint64_t off, uint32_t size) { struct reftable_buf *b = v; assert(off + size <= b->len); @@ -78,8 +78,8 @@ static void file_close(void *v) reftable_free(b); } -static int file_read_block(void *v, struct reftable_block *dest, uint64_t off, - uint32_t size) +static ssize_t file_read_block(void *v, struct reftable_block *dest, uint64_t off, + uint32_t size) { struct file_block_source *b = v; assert(off + size <= b->size); diff --git a/reftable/reader.c b/reftable/reader.c index ea82955c9b..24bae50ac2 100644 --- a/reftable/reader.c +++ b/reftable/reader.c @@ -20,11 +20,11 @@ uint64_t block_source_size(struct reftable_block_source *source) return source->ops->size(source->arg); } -int block_source_read_block(struct reftable_block_source *source, - struct reftable_block *dest, uint64_t off, - uint32_t size) +ssize_t block_source_read_block(struct reftable_block_source *source, + struct reftable_block *dest, uint64_t off, + uint32_t size) { - int result = source->ops->read_block(source->arg, dest, off, size); + ssize_t result = source->ops->read_block(source->arg, dest, off, size); dest->source = *source; return result; } @@ -57,14 +57,17 @@ static int reader_get_block(struct reftable_reader *r, struct reftable_block *dest, uint64_t off, uint32_t sz) { + ssize_t bytes_read; if (off >= r->size) return 0; - - if (off + sz > r->size) { + if (off + sz > r->size) sz = r->size - off; - } - return block_source_read_block(&r->source, dest, off, sz); + bytes_read = block_source_read_block(&r->source, dest, off, sz); + if (bytes_read < 0) + return (int)bytes_read; + + return 0; } enum reftable_hash reftable_reader_hash_id(struct reftable_reader *r) @@ -601,6 +604,7 @@ int reftable_reader_new(struct reftable_reader **out, struct reftable_reader *r; uint64_t file_size = block_source_size(source); uint32_t read_size; + ssize_t bytes_read; int err; REFTABLE_CALLOC_ARRAY(r, 1); @@ -619,8 +623,8 @@ int reftable_reader_new(struct reftable_reader **out, goto done; } - err = block_source_read_block(source, &header, 0, read_size); - if (err != read_size) { + bytes_read = block_source_read_block(source, &header, 0, read_size); + if (bytes_read < 0 || (size_t)bytes_read != read_size) { err = REFTABLE_IO_ERROR; goto done; } @@ -645,9 +649,9 @@ int reftable_reader_new(struct reftable_reader **out, r->hash_id = 0; r->refcount = 1; - err = block_source_read_block(source, &footer, r->size, - footer_size(r->version)); - if (err != footer_size(r->version)) { + bytes_read = block_source_read_block(source, &footer, r->size, + footer_size(r->version)); + if (bytes_read < 0 || (size_t)bytes_read != footer_size(r->version)) { err = REFTABLE_IO_ERROR; goto done; } @@ -662,6 +666,8 @@ done: reftable_block_done(&footer); reftable_block_done(&header); if (err) { + if (r) + reftable_free(r->name); reftable_free(r); block_source_close(source); } @@ -750,7 +756,7 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r, struct table_iter *ti; struct filtering_ref_iterator *filter = NULL; struct filtering_ref_iterator empty = FILTERING_REF_ITERATOR_INIT; - int oid_len = hash_size(r->hash_id); + uint32_t oid_len = hash_size(r->hash_id); int err; REFTABLE_ALLOC_ARRAY(ti, 1); diff --git a/reftable/reader.h b/reftable/reader.h index d2b48a4849..bb72108a6f 100644 --- a/reftable/reader.h +++ b/reftable/reader.h @@ -16,9 +16,9 @@ https://developers.google.com/open-source/licenses/bsd uint64_t block_source_size(struct reftable_block_source *source); -int block_source_read_block(struct reftable_block_source *source, - struct reftable_block *dest, uint64_t off, - uint32_t size); +ssize_t block_source_read_block(struct reftable_block_source *source, + struct reftable_block *dest, uint64_t off, + uint32_t size); void block_source_close(struct reftable_block_source *source); /* metadata for a block type */ diff --git a/reftable/record.c b/reftable/record.c index 04429d23fe..8919df8a4d 100644 --- a/reftable/record.c +++ b/reftable/record.c @@ -21,47 +21,49 @@ static void *reftable_record_data(struct reftable_record *rec); int get_var_int(uint64_t *dest, struct string_view *in) { - int ptr = 0; + const unsigned char *buf = in->buf; + unsigned char c; uint64_t val; - if (in->len == 0) + if (!in->len) return -1; - val = in->buf[ptr] & 0x7f; - - while (in->buf[ptr] & 0x80) { - ptr++; - if (ptr > in->len) { + c = *buf++; + val = c & 0x7f; + + while (c & 0x80) { + /* + * We use a micro-optimization here: whenever we see that the + * 0x80 bit is set, we know that the remainder of the value + * cannot be 0. The zero-values thus doesn't need to be encoded + * at all, which is why we subtract 1 when encoding and add 1 + * when decoding. + * + * This allows us to save a byte in some edge cases. + */ + val += 1; + if (!val || (val & (uint64_t)(~0ULL << (64 - 7)))) + return -1; /* overflow */ + if (buf >= in->buf + in->len) return -1; - } - val = (val + 1) << 7 | (uint64_t)(in->buf[ptr] & 0x7f); + c = *buf++; + val = (val << 7) + (c & 0x7f); } *dest = val; - return ptr + 1; + return buf - in->buf; } -int put_var_int(struct string_view *dest, uint64_t val) +int put_var_int(struct string_view *dest, uint64_t value) { - uint8_t buf[10] = { 0 }; - int i = 9; - int n = 0; - buf[i] = (uint8_t)(val & 0x7f); - i--; - while (1) { - val >>= 7; - if (!val) { - break; - } - val--; - buf[i] = 0x80 | (uint8_t)(val & 0x7f); - i--; - } - - n = sizeof(buf) - i - 1; - if (dest->len < n) + unsigned char varint[10]; + unsigned pos = sizeof(varint) - 1; + varint[pos] = value & 0x7f; + while (value >>= 7) + varint[--pos] = 0x80 | (--value & 0x7f); + if (dest->len < sizeof(varint) - pos) return -1; - memcpy(dest->buf, &buf[i + 1], n); - return n; + memcpy(dest->buf, varint + pos, sizeof(varint) - pos); + return sizeof(varint) - pos; } int reftable_is_block_type(uint8_t typ) @@ -124,7 +126,7 @@ static int decode_string(struct reftable_buf *dest, struct string_view in) static int encode_string(const char *str, struct string_view s) { struct string_view start = s; - int l = strlen(str); + size_t l = strlen(str); int n = put_var_int(&s, l); if (n < 0) return -1; @@ -142,9 +144,9 @@ int reftable_encode_key(int *restart, struct string_view dest, uint8_t extra) { struct string_view start = dest; - int prefix_len = common_prefix_size(&prev_key, &key); + size_t prefix_len = common_prefix_size(&prev_key, &key); uint64_t suffix_len = key.len - prefix_len; - int n = put_var_int(&dest, (uint64_t)prefix_len); + int n = put_var_int(&dest, prefix_len); if (n < 0) return -1; string_view_consume(&dest, n); @@ -227,7 +229,7 @@ static int reftable_ref_record_key(const void *r, struct reftable_buf *dest) } static int reftable_ref_record_copy_from(void *rec, const void *src_rec, - int hash_size) + uint32_t hash_size) { struct reftable_ref_record *ref = rec; const struct reftable_ref_record *src = src_rec; @@ -235,8 +237,6 @@ static int reftable_ref_record_copy_from(void *rec, const void *src_rec, size_t refname_cap = 0; int err; - assert(hash_size > 0); - SWAP(refname, ref->refname); SWAP(refname_cap, ref->refname_cap); reftable_ref_record_release(ref); @@ -317,13 +317,12 @@ static uint8_t reftable_ref_record_val_type(const void *rec) } static int reftable_ref_record_encode(const void *rec, struct string_view s, - int hash_size) + uint32_t hash_size) { const struct reftable_ref_record *r = (const struct reftable_ref_record *)rec; struct string_view start = s; int n = put_var_int(&s, r->update_index); - assert(hash_size > 0); if (n < 0) return -1; string_view_consume(&s, n); @@ -363,7 +362,7 @@ static int reftable_ref_record_encode(const void *rec, struct string_view s, static int reftable_ref_record_decode(void *rec, struct reftable_buf key, uint8_t val_type, struct string_view in, - int hash_size, struct reftable_buf *scratch) + uint32_t hash_size, struct reftable_buf *scratch) { struct reftable_ref_record *r = rec; struct string_view start = in; @@ -372,8 +371,6 @@ static int reftable_ref_record_decode(void *rec, struct reftable_buf key, size_t refname_cap = 0; int n, err; - assert(hash_size > 0); - n = get_var_int(&update_index, &in); if (n < 0) return n; @@ -449,7 +446,7 @@ static int reftable_ref_record_is_deletion_void(const void *p) } static int reftable_ref_record_equal_void(const void *a, - const void *b, int hash_size) + const void *b, uint32_t hash_size) { struct reftable_ref_record *ra = (struct reftable_ref_record *) a; struct reftable_ref_record *rb = (struct reftable_ref_record *) b; @@ -493,7 +490,7 @@ static void reftable_obj_record_release(void *rec) } static int reftable_obj_record_copy_from(void *rec, const void *src_rec, - int hash_size UNUSED) + uint32_t hash_size UNUSED) { struct reftable_obj_record *obj = rec; const struct reftable_obj_record *src = src_rec; @@ -525,7 +522,7 @@ static uint8_t reftable_obj_record_val_type(const void *rec) } static int reftable_obj_record_encode(const void *rec, struct string_view s, - int hash_size UNUSED) + uint32_t hash_size UNUSED) { const struct reftable_obj_record *r = rec; struct string_view start = s; @@ -560,7 +557,7 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s, static int reftable_obj_record_decode(void *rec, struct reftable_buf key, uint8_t val_type, struct string_view in, - int hash_size UNUSED, + uint32_t hash_size UNUSED, struct reftable_buf *scratch UNUSED) { struct string_view start = in; @@ -568,7 +565,6 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key, uint64_t count = val_type; int n = 0; uint64_t last; - int j; reftable_obj_record_release(r); @@ -603,8 +599,7 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key, string_view_consume(&in, n); last = r->offsets[0]; - j = 1; - while (j < count) { + for (uint64_t j = 1; j < count; j++) { uint64_t delta = 0; int n = get_var_int(&delta, &in); if (n < 0) { @@ -613,7 +608,6 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key, string_view_consume(&in, n); last = r->offsets[j] = (delta + last); - j++; } return start.len - in.len; } @@ -624,7 +618,7 @@ static int not_a_deletion(const void *p UNUSED) } static int reftable_obj_record_equal_void(const void *a, const void *b, - int hash_size UNUSED) + uint32_t hash_size UNUSED) { struct reftable_obj_record *ra = (struct reftable_obj_record *) a; struct reftable_obj_record *rb = (struct reftable_obj_record *) b; @@ -699,7 +693,7 @@ static int reftable_log_record_key(const void *r, struct reftable_buf *dest) } static int reftable_log_record_copy_from(void *rec, const void *src_rec, - int hash_size) + uint32_t hash_size) { struct reftable_log_record *dst = rec; const struct reftable_log_record *src = @@ -780,7 +774,7 @@ static uint8_t reftable_log_record_val_type(const void *rec) } static int reftable_log_record_encode(const void *rec, struct string_view s, - int hash_size) + uint32_t hash_size) { const struct reftable_log_record *r = rec; struct string_view start = s; @@ -828,7 +822,7 @@ static int reftable_log_record_encode(const void *rec, struct string_view s, static int reftable_log_record_decode(void *rec, struct reftable_buf key, uint8_t val_type, struct string_view in, - int hash_size, struct reftable_buf *scratch) + uint32_t hash_size, struct reftable_buf *scratch) { struct string_view start = in; struct reftable_log_record *r = rec; @@ -976,7 +970,7 @@ static int null_streq(const char *a, const char *b) } static int reftable_log_record_equal_void(const void *a, - const void *b, int hash_size) + const void *b, uint32_t hash_size) { return reftable_log_record_equal((struct reftable_log_record *) a, (struct reftable_log_record *) b, @@ -1000,7 +994,7 @@ static int reftable_log_record_cmp_void(const void *_a, const void *_b) } int reftable_log_record_equal(const struct reftable_log_record *a, - const struct reftable_log_record *b, int hash_size) + const struct reftable_log_record *b, uint32_t hash_size) { if (!(null_streq(a->refname, b->refname) && a->update_index == b->update_index && @@ -1054,7 +1048,7 @@ static int reftable_index_record_key(const void *r, struct reftable_buf *dest) } static int reftable_index_record_copy_from(void *rec, const void *src_rec, - int hash_size UNUSED) + uint32_t hash_size UNUSED) { struct reftable_index_record *dst = rec; const struct reftable_index_record *src = src_rec; @@ -1081,7 +1075,7 @@ static uint8_t reftable_index_record_val_type(const void *rec UNUSED) } static int reftable_index_record_encode(const void *rec, struct string_view out, - int hash_size UNUSED) + uint32_t hash_size UNUSED) { const struct reftable_index_record *r = (const struct reftable_index_record *)rec; @@ -1099,7 +1093,7 @@ static int reftable_index_record_encode(const void *rec, struct string_view out, static int reftable_index_record_decode(void *rec, struct reftable_buf key, uint8_t val_type UNUSED, struct string_view in, - int hash_size UNUSED, + uint32_t hash_size UNUSED, struct reftable_buf *scratch UNUSED) { struct string_view start = in; @@ -1120,7 +1114,7 @@ static int reftable_index_record_decode(void *rec, struct reftable_buf key, } static int reftable_index_record_equal(const void *a, const void *b, - int hash_size UNUSED) + uint32_t hash_size UNUSED) { struct reftable_index_record *ia = (struct reftable_index_record *) a; struct reftable_index_record *ib = (struct reftable_index_record *) b; @@ -1154,14 +1148,14 @@ int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest) } int reftable_record_encode(struct reftable_record *rec, struct string_view dest, - int hash_size) + uint32_t hash_size) { return reftable_record_vtable(rec)->encode(reftable_record_data(rec), dest, hash_size); } int reftable_record_copy_from(struct reftable_record *rec, - struct reftable_record *src, int hash_size) + struct reftable_record *src, uint32_t hash_size) { assert(src->type == rec->type); @@ -1176,7 +1170,7 @@ uint8_t reftable_record_val_type(struct reftable_record *rec) } int reftable_record_decode(struct reftable_record *rec, struct reftable_buf key, - uint8_t extra, struct string_view src, int hash_size, + uint8_t extra, struct string_view src, uint32_t hash_size, struct reftable_buf *scratch) { return reftable_record_vtable(rec)->decode(reftable_record_data(rec), @@ -1203,7 +1197,7 @@ int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b) reftable_record_data(a), reftable_record_data(b)); } -int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size) +int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size) { if (a->type != b->type) return 0; @@ -1211,7 +1205,7 @@ int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, reftable_record_data(a), reftable_record_data(b), hash_size); } -static int hash_equal(const unsigned char *a, const unsigned char *b, int hash_size) +static int hash_equal(const unsigned char *a, const unsigned char *b, uint32_t hash_size) { if (a && b) return !memcmp(a, b, hash_size); @@ -1220,9 +1214,8 @@ static int hash_equal(const unsigned char *a, const unsigned char *b, int hash_s } int reftable_ref_record_equal(const struct reftable_ref_record *a, - const struct reftable_ref_record *b, int hash_size) + const struct reftable_ref_record *b, uint32_t hash_size) { - assert(hash_size > 0); if (!null_streq(a->refname, b->refname)) return 0; diff --git a/reftable/record.h b/reftable/record.h index 25aa908c85..c7755a4d75 100644 --- a/reftable/record.h +++ b/reftable/record.h @@ -32,8 +32,10 @@ static inline void string_view_consume(struct string_view *s, int n) s->len -= n; } -/* utilities for de/encoding varints */ - +/* + * Decode and encode a varint. Returns the number of bytes read/written, or a + * negative value in case encoding/decoding the varint has failed. + */ int get_var_int(uint64_t *dest, struct string_view *in); int put_var_int(struct string_view *dest, uint64_t val); @@ -45,18 +47,18 @@ struct reftable_record_vtable { /* The record type of ('r' for ref). */ uint8_t type; - int (*copy_from)(void *dest, const void *src, int hash_size); + int (*copy_from)(void *dest, const void *src, uint32_t hash_size); /* a value of [0..7], indicating record subvariants (eg. ref vs. symref * vs ref deletion) */ uint8_t (*val_type)(const void *rec); /* encodes rec into dest, returning how much space was used. */ - int (*encode)(const void *rec, struct string_view dest, int hash_size); + int (*encode)(const void *rec, struct string_view dest, uint32_t hash_size); /* decode data from `src` into the record. */ int (*decode)(void *rec, struct reftable_buf key, uint8_t extra, - struct string_view src, int hash_size, + struct string_view src, uint32_t hash_size, struct reftable_buf *scratch); /* deallocate and null the record. */ @@ -66,16 +68,13 @@ struct reftable_record_vtable { int (*is_deletion)(const void *rec); /* Are two records equal? This assumes they have the same type. Returns 0 for non-equal. */ - int (*equal)(const void *a, const void *b, int hash_size); + int (*equal)(const void *a, const void *b, uint32_t hash_size); /* * Compare keys of two records with each other. The records must have * the same type. */ int (*cmp)(const void *a, const void *b); - - /* Print on stdout, for debugging. */ - void (*print)(const void *rec, int hash_size); }; /* returns true for recognized block types. Block start with the block type. */ @@ -136,16 +135,16 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ); /* see struct record_vtable */ int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b); -int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size); +int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size); int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest); int reftable_record_copy_from(struct reftable_record *rec, - struct reftable_record *src, int hash_size); + struct reftable_record *src, uint32_t hash_size); uint8_t reftable_record_val_type(struct reftable_record *rec); int reftable_record_encode(struct reftable_record *rec, struct string_view dest, - int hash_size); + uint32_t hash_size); int reftable_record_decode(struct reftable_record *rec, struct reftable_buf key, uint8_t extra, struct string_view src, - int hash_size, struct reftable_buf *scratch); + uint32_t hash_size, struct reftable_buf *scratch); int reftable_record_is_deletion(struct reftable_record *rec); static inline uint8_t reftable_record_type(struct reftable_record *rec) diff --git a/reftable/reftable-blocksource.h b/reftable/reftable-blocksource.h index 5aa3990a57..6b326aa5ea 100644 --- a/reftable/reftable-blocksource.h +++ b/reftable/reftable-blocksource.h @@ -22,7 +22,7 @@ struct reftable_block_source { * so it can return itself into the pool. */ struct reftable_block { uint8_t *data; - int len; + size_t len; struct reftable_block_source source; }; @@ -31,10 +31,13 @@ struct reftable_block_source_vtable { /* returns the size of a block source */ uint64_t (*size)(void *source); - /* reads a segment from the block source. It is an error to read - beyond the end of the block */ - int (*read_block)(void *source, struct reftable_block *dest, - uint64_t off, uint32_t size); + /* + * Reads a segment from the block source. It is an error to read beyond + * the end of the block. + */ + ssize_t (*read_block)(void *source, struct reftable_block *dest, + uint64_t off, uint32_t size); + /* mark the block as read; may return the data back to malloc */ void (*return_block)(void *source, struct reftable_block *blockp); diff --git a/reftable/reftable-error.h b/reftable/reftable-error.h index f404826562..a7e33d964d 100644 --- a/reftable/reftable-error.h +++ b/reftable/reftable-error.h @@ -30,6 +30,7 @@ enum reftable_error { /* Misuse of the API: * - on writing a record with NULL refname. + * - on writing a record before setting the writer limits. * - on writing a reftable_ref_record outside the table limits * - on writing a ref or log record before the stack's * next_update_inde*x diff --git a/reftable/reftable-record.h b/reftable/reftable-record.h index ddd48eb579..931e594744 100644 --- a/reftable/reftable-record.h +++ b/reftable/reftable-record.h @@ -65,7 +65,7 @@ void reftable_ref_record_release(struct reftable_ref_record *ref); /* returns whether two reftable_ref_records are the same. Useful for testing. */ int reftable_ref_record_equal(const struct reftable_ref_record *a, - const struct reftable_ref_record *b, int hash_size); + const struct reftable_ref_record *b, uint32_t hash_size); /* reftable_log_record holds a reflog entry */ struct reftable_log_record { @@ -105,6 +105,6 @@ void reftable_log_record_release(struct reftable_log_record *log); /* returns whether two records are equal. Useful for testing. */ int reftable_log_record_equal(const struct reftable_log_record *a, - const struct reftable_log_record *b, int hash_size); + const struct reftable_log_record *b, uint32_t hash_size); #endif diff --git a/reftable/reftable-writer.h b/reftable/reftable-writer.h index 5f9afa620b..1befe3b07c 100644 --- a/reftable/reftable-writer.h +++ b/reftable/reftable-writer.h @@ -84,7 +84,7 @@ struct reftable_block_stats { /* total number of entries written */ int entries; /* total number of key restarts */ - int restarts; + uint32_t restarts; /* total number of blocks */ int blocks; /* total number of index blocks */ @@ -124,17 +124,21 @@ int reftable_writer_new(struct reftable_writer **out, int (*flush_func)(void *), void *writer_arg, const struct reftable_write_options *opts); -/* Set the range of update indices for the records we will add. When writing a - table into a stack, the min should be at least - reftable_stack_next_update_index(), or REFTABLE_API_ERROR is returned. - - For transactional updates to a stack, typically min==max, and the - update_index can be obtained by inspeciting the stack. When converting an - existing ref database into a single reftable, this would be a range of - update-index timestamps. +/* + * Set the range of update indices for the records we will add. When writing a + * table into a stack, the min should be at least + * reftable_stack_next_update_index(), or REFTABLE_API_ERROR is returned. + * + * For transactional updates to a stack, typically min==max, and the + * update_index can be obtained by inspeciting the stack. When converting an + * existing ref database into a single reftable, this would be a range of + * update-index timestamps. + * + * The function should be called before adding any records to the writer. If not + * it will fail with REFTABLE_API_ERROR. */ -void reftable_writer_set_limits(struct reftable_writer *w, uint64_t min, - uint64_t max); +int reftable_writer_set_limits(struct reftable_writer *w, uint64_t min, + uint64_t max); /* Add a reftable_ref_record. The record should have names that come after diff --git a/reftable/stack.c b/reftable/stack.c index 531660a49f..6c4e8be19b 100644 --- a/reftable/stack.c +++ b/reftable/stack.c @@ -220,9 +220,9 @@ void reftable_stack_destroy(struct reftable_stack *st) } if (st->readers) { - int i = 0; struct reftable_buf filename = REFTABLE_BUF_INIT; - for (i = 0; i < st->readers_len; i++) { + + for (size_t i = 0; i < st->readers_len; i++) { const char *name = reader_name(st->readers[i]); int try_unlinking = 1; @@ -238,6 +238,7 @@ void reftable_stack_destroy(struct reftable_stack *st) unlink(filename.buf); } } + reftable_buf_release(&filename); st->readers_len = 0; REFTABLE_FREE_AND_NULL(st->readers); @@ -493,7 +494,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st, close(fd); fd = -1; - delay = delay + (delay * rand()) / RAND_MAX + 1; + delay = delay + (delay * git_rand(CSPRNG_BYTES_INSECURE)) / UINT32_MAX + 1; sleep_millisec(delay); } @@ -568,7 +569,6 @@ static int stack_uptodate(struct reftable_stack *st) { char **names = NULL; int err; - int i = 0; /* * When we have cached stat information available then we use it to @@ -608,7 +608,7 @@ static int stack_uptodate(struct reftable_stack *st) if (err < 0) return err; - for (i = 0; i < st->readers_len; i++) { + for (size_t i = 0; i < st->readers_len; i++) { if (!names[i]) { err = 1; goto done; @@ -659,7 +659,7 @@ int reftable_stack_add(struct reftable_stack *st, static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max) { char buf[100]; - uint32_t rnd = (uint32_t)git_rand(); + uint32_t rnd = git_rand(CSPRNG_BYTES_INSECURE); snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x", min, max, rnd); reftable_buf_reset(dest); @@ -1058,8 +1058,10 @@ static int stack_write_compact(struct reftable_stack *st, for (size_t i = first; i <= last; i++) st->stats.bytes += st->readers[i]->size; - reftable_writer_set_limits(wr, st->readers[first]->min_update_index, - st->readers[last]->max_update_index); + err = reftable_writer_set_limits(wr, st->readers[first]->min_update_index, + st->readers[last]->max_update_index); + if (err < 0) + goto done; err = reftable_merged_table_new(&mt, st->readers + first, subtabs_len, st->opts.hash_id); @@ -1767,14 +1769,12 @@ static int reftable_stack_clean_locked(struct reftable_stack *st) } while ((d = readdir(dir))) { - int i = 0; int found = 0; if (!is_table_name(d->d_name)) continue; - for (i = 0; !found && i < st->readers_len; i++) { + for (size_t i = 0; !found && i < st->readers_len; i++) found = !strcmp(reader_name(st->readers[i]), d->d_name); - } if (found) continue; diff --git a/reftable/system.h b/reftable/system.h index 5274eca1d0..d02eacea8f 100644 --- a/reftable/system.h +++ b/reftable/system.h @@ -11,9 +11,8 @@ https://developers.google.com/open-source/licenses/bsd /* This header glues the reftable library to the rest of Git */ -#define DISABLE_SIGN_COMPARE_WARNINGS - #include "git-compat-util.h" +#include "compat/zlib-compat.h" /* * An implementation-specific temporary file. By making this specific to the diff --git a/reftable/writer.c b/reftable/writer.c index 740c98038e..f3ab1035d6 100644 --- a/reftable/writer.c +++ b/reftable/writer.c @@ -179,11 +179,24 @@ int reftable_writer_new(struct reftable_writer **out, return 0; } -void reftable_writer_set_limits(struct reftable_writer *w, uint64_t min, +int reftable_writer_set_limits(struct reftable_writer *w, uint64_t min, uint64_t max) { + /* + * Set the min/max update index limits for the reftable writer. + * This must be called before adding any records, since: + * - The 'next' field gets set after writing the first block. + * - The 'last_key' field updates with each new record (but resets + * after sections). + * Returns REFTABLE_API_ERROR if called after writing has begun. + */ + if (w->next || w->last_key.len) + return REFTABLE_API_ERROR; + w->min_update_index = min; w->max_update_index = max; + + return 0; } static void writer_release(struct reftable_writer *w) @@ -577,7 +590,7 @@ static int writer_finish_section(struct reftable_writer *w) struct common_prefix_arg { struct reftable_buf *last; - int max; + size_t max; }; static void update_common(void *void_arg, void *key) @@ -585,10 +598,9 @@ static void update_common(void *void_arg, void *key) struct common_prefix_arg *arg = void_arg; struct obj_index_tree_node *entry = key; if (arg->last) { - int n = common_prefix_size(&entry->hash, arg->last); - if (n > arg->max) { + size_t n = common_prefix_size(&entry->hash, arg->last); + if (n > arg->max) arg->max = n; - } } arg->last = &entry->hash; } diff --git a/remote-curl.c b/remote-curl.c index a24e3a8b9a..1273507a96 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -942,7 +942,7 @@ static int post_rpc(struct rpc_state *rpc, int stateless_connect, int flush_rece do { err = probe_rpc(rpc, &results); if (err == HTTP_REAUTH) - credential_fill(&http_auth, 0); + credential_fill(the_repository, &http_auth, 0); } while (err == HTTP_REAUTH); if (err != HTTP_OK) return -1; @@ -1064,7 +1064,7 @@ retry: rpc->any_written = 0; err = run_slot(slot, NULL); if (err == HTTP_REAUTH && !large_request) { - credential_fill(&http_auth, 0); + credential_fill(the_repository, &http_auth, 0); curl_slist_free_all(headers); goto retry; } @@ -294,6 +294,7 @@ static void add_instead_of(struct rewrite *rewrite, const char *instead_of) rewrite->instead_of_nr++; } +#ifndef WITH_BREAKING_CHANGES static const char *skip_spaces(const char *s) { while (isspace(*s)) @@ -301,14 +302,33 @@ static const char *skip_spaces(const char *s) return s; } +static void warn_about_deprecated_remote_type(const char *type, + const struct remote *remote) +{ + warning(_("reading remote from \"%s/%s\", which is nominated for removal.\n" + "\n" + "If you still use the \"remotes/\" directory it is recommended to\n" + "migrate to config-based remotes:\n" + "\n" + "\tgit remote rename %s %s\n" + "\n" + "If you cannot, please let us know why you still need to use it by\n" + "sending an e-mail to <git@vger.kernel.org>."), + type, remote->name, remote->name, remote->name); +} + static void read_remotes_file(struct remote_state *remote_state, struct remote *remote) { struct strbuf buf = STRBUF_INIT; - FILE *f = fopen_or_warn(git_path("remotes/%s", remote->name), "r"); + FILE *f = fopen_or_warn(repo_git_path_append(the_repository, &buf, + "remotes/%s", remote->name), "r"); if (!f) - return; + goto out; + + warn_about_deprecated_remote_type("remotes", remote); + remote->configured_in_repo = 1; remote->origin = REMOTE_REMOTES; while (strbuf_getline(&buf, f) != EOF) { @@ -324,8 +344,10 @@ static void read_remotes_file(struct remote_state *remote_state, else if (skip_prefix(buf.buf, "Pull:", &v)) refspec_append(&remote->fetch, skip_spaces(v)); } - strbuf_release(&buf); fclose(f); + +out: + strbuf_release(&buf); } static void read_branches_file(struct remote_state *remote_state, @@ -333,18 +355,19 @@ static void read_branches_file(struct remote_state *remote_state, { char *frag, *to_free = NULL; struct strbuf buf = STRBUF_INIT; - FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r"); + FILE *f = fopen_or_warn(repo_git_path_append(the_repository, &buf, + "branches/%s", remote->name), "r"); if (!f) - return; + goto out; + + warn_about_deprecated_remote_type("branches", remote); strbuf_getline_lf(&buf, f); fclose(f); strbuf_trim(&buf); - if (!buf.len) { - strbuf_release(&buf); - return; - } + if (!buf.len) + goto out; remote->configured_in_repo = 1; remote->origin = REMOTE_BRANCHES; @@ -372,9 +395,11 @@ static void read_branches_file(struct remote_state *remote_state, refspec_appendf(&remote->push, "HEAD:refs/heads/%s", frag); remote->fetch_tags = 1; /* always auto-follow */ +out: strbuf_release(&buf); free(to_free); } +#endif /* WITH_BREAKING_CHANGES */ static int handle_config(const char *key, const char *value, const struct config_context *ctx, void *cb) @@ -591,6 +616,7 @@ static void read_config(struct repository *repo, int early) alias_all_urls(repo->remote_state); } +#ifndef WITH_BREAKING_CHANGES static int valid_remote_nick(const char *name) { if (!name[0] || is_dot_or_dotdot(name)) @@ -602,6 +628,7 @@ static int valid_remote_nick(const char *name) return 0; return 1; } +#endif /* WITH_BREAKING_CHANGES */ static const char *remotes_remote_for_branch(struct remote_state *remote_state, struct branch *branch, @@ -744,12 +771,14 @@ remotes_remote_get_1(struct remote_state *remote_state, const char *name, &name_given); ret = make_remote(remote_state, name, 0); +#ifndef WITH_BREAKING_CHANGES if (valid_remote_nick(name) && have_git_dir()) { if (!valid_remote(ret)) read_remotes_file(remote_state, ret); if (!valid_remote(ret)) read_branches_file(remote_state, ret); } +#endif /* WITH_BREAKING_CHANGES */ if (name_given && !valid_remote(ret)) add_url_alias(remote_state, ret, name); if (!valid_remote(ret)) @@ -907,210 +936,9 @@ void ref_push_report_free(struct ref_push_report *report) } } -static int match_name_with_pattern(const char *key, const char *name, - const char *value, char **result) -{ - const char *kstar = strchr(key, '*'); - size_t klen; - size_t ksuffixlen; - size_t namelen; - int ret; - if (!kstar) - die(_("key '%s' of pattern had no '*'"), key); - klen = kstar - key; - ksuffixlen = strlen(kstar + 1); - namelen = strlen(name); - ret = !strncmp(name, key, klen) && namelen >= klen + ksuffixlen && - !memcmp(name + namelen - ksuffixlen, kstar + 1, ksuffixlen); - if (ret && value) { - struct strbuf sb = STRBUF_INIT; - const char *vstar = strchr(value, '*'); - if (!vstar) - die(_("value '%s' of pattern has no '*'"), value); - strbuf_add(&sb, value, vstar - value); - strbuf_add(&sb, name + klen, namelen - klen - ksuffixlen); - strbuf_addstr(&sb, vstar + 1); - *result = strbuf_detach(&sb, NULL); - } - return ret; -} - -static int refspec_match(const struct refspec_item *refspec, - const char *name) -{ - if (refspec->pattern) - return match_name_with_pattern(refspec->src, name, NULL, NULL); - - return !strcmp(refspec->src, name); -} - -int omit_name_by_refspec(const char *name, struct refspec *rs) -{ - int i; - - for (i = 0; i < rs->nr; i++) { - if (rs->items[i].negative && refspec_match(&rs->items[i], name)) - return 1; - } - return 0; -} - -struct ref *apply_negative_refspecs(struct ref *ref_map, struct refspec *rs) -{ - struct ref **tail; - - for (tail = &ref_map; *tail; ) { - struct ref *ref = *tail; - - if (omit_name_by_refspec(ref->name, rs)) { - *tail = ref->next; - free(ref->peer_ref); - free(ref); - } else - tail = &ref->next; - } - - return ref_map; -} - -static int query_matches_negative_refspec(struct refspec *rs, struct refspec_item *query) -{ - int i, matched_negative = 0; - int find_src = !query->src; - struct string_list reversed = STRING_LIST_INIT_DUP; - const char *needle = find_src ? query->dst : query->src; - - /* - * Check whether the queried ref matches any negative refpsec. If so, - * then we should ultimately treat this as not matching the query at - * all. - * - * Note that negative refspecs always match the source, but the query - * item uses the destination. To handle this, we apply pattern - * refspecs in reverse to figure out if the query source matches any - * of the negative refspecs. - * - * The first loop finds and expands all positive refspecs - * matched by the queried ref. - * - * The second loop checks if any of the results of the first loop - * match any negative refspec. - */ - for (i = 0; i < rs->nr; i++) { - struct refspec_item *refspec = &rs->items[i]; - char *expn_name; - - if (refspec->negative) - continue; - - /* Note the reversal of src and dst */ - if (refspec->pattern) { - const char *key = refspec->dst ? refspec->dst : refspec->src; - const char *value = refspec->src; - - if (match_name_with_pattern(key, needle, value, &expn_name)) - string_list_append_nodup(&reversed, expn_name); - } else if (refspec->matching) { - /* For the special matching refspec, any query should match */ - string_list_append(&reversed, needle); - } else if (!refspec->src) { - BUG("refspec->src should not be null here"); - } else if (!strcmp(needle, refspec->src)) { - string_list_append(&reversed, refspec->src); - } - } - - for (i = 0; !matched_negative && i < reversed.nr; i++) { - if (omit_name_by_refspec(reversed.items[i].string, rs)) - matched_negative = 1; - } - - string_list_clear(&reversed, 0); - - return matched_negative; -} - -static void query_refspecs_multiple(struct refspec *rs, - struct refspec_item *query, - struct string_list *results) -{ - int i; - int find_src = !query->src; - - if (find_src && !query->dst) - BUG("query_refspecs_multiple: need either src or dst"); - - if (query_matches_negative_refspec(rs, query)) - return; - - for (i = 0; i < rs->nr; i++) { - struct refspec_item *refspec = &rs->items[i]; - const char *key = find_src ? refspec->dst : refspec->src; - const char *value = find_src ? refspec->src : refspec->dst; - const char *needle = find_src ? query->dst : query->src; - char **result = find_src ? &query->src : &query->dst; - - if (!refspec->dst || refspec->negative) - continue; - if (refspec->pattern) { - if (match_name_with_pattern(key, needle, value, result)) - string_list_append_nodup(results, *result); - } else if (!strcmp(needle, key)) { - string_list_append(results, value); - } - } -} - -int query_refspecs(struct refspec *rs, struct refspec_item *query) -{ - int i; - int find_src = !query->src; - const char *needle = find_src ? query->dst : query->src; - char **result = find_src ? &query->src : &query->dst; - - if (find_src && !query->dst) - BUG("query_refspecs: need either src or dst"); - - if (query_matches_negative_refspec(rs, query)) - return -1; - - for (i = 0; i < rs->nr; i++) { - struct refspec_item *refspec = &rs->items[i]; - const char *key = find_src ? refspec->dst : refspec->src; - const char *value = find_src ? refspec->src : refspec->dst; - - if (!refspec->dst || refspec->negative) - continue; - if (refspec->pattern) { - if (match_name_with_pattern(key, needle, value, result)) { - query->force = refspec->force; - return 0; - } - } else if (!strcmp(needle, key)) { - *result = xstrdup(value); - query->force = refspec->force; - return 0; - } - } - return -1; -} - -char *apply_refspecs(struct refspec *rs, const char *name) -{ - struct refspec_item query; - - memset(&query, 0, sizeof(struct refspec_item)); - query.src = (char *)name; - - if (query_refspecs(rs, &query)) - return NULL; - - return query.dst; -} - int remote_find_tracking(struct remote *remote, struct refspec_item *refspec) { - return query_refspecs(&remote->fetch, refspec); + return refspec_find_match(&remote->fetch, refspec); } static struct ref *alloc_ref_with_prefix(const char *prefix, size_t prefixlen, @@ -1234,7 +1062,7 @@ int count_refspec_match(const char *pattern, } } -static void tail_link_ref(struct ref *ref, struct ref ***tail) +void tail_link_ref(struct ref *ref, struct ref ***tail) { **tail = ref; while (ref->next) @@ -1497,9 +1325,9 @@ static char *get_ref_match(const struct refspec *rs, const struct ref *ref, const char *dst_side = item->dst ? item->dst : item->src; int match; if (direction == FROM_SRC) - match = match_name_with_pattern(item->src, ref->name, dst_side, &name); + match = match_refname_with_pattern(item->src, ref->name, dst_side, &name); else - match = match_name_with_pattern(dst_side, ref->name, item->src, &name); + match = match_refname_with_pattern(dst_side, ref->name, item->src, &name); if (match) { matching_refs = i; break; @@ -1535,7 +1363,7 @@ static struct ref **tail_ref(struct ref **head) struct tips { struct commit **tip; - int nr, alloc; + size_t nr, alloc; }; static void add_to_tips(struct tips *tips, const struct object_id *oid) @@ -1602,7 +1430,7 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds const int reachable_flag = 1; struct commit_list *found_commits; struct commit **src_commits; - int nr_src_commits = 0, alloc_src_commits = 16; + size_t nr_src_commits = 0, alloc_src_commits = 16; ALLOC_ARRAY(src_commits, alloc_src_commits); for_each_string_list_item(item, &src_tag) { @@ -2117,7 +1945,7 @@ static struct ref *get_expanded_map(const struct ref *remote_refs, if (strchr(ref->name, '^')) continue; /* a dereference item */ - if (match_name_with_pattern(refspec->src, ref->name, + if (match_refname_with_pattern(refspec->src, ref->name, refspec->dst, &expn_name) && !ignore_symref_update(expn_name, &scratch)) { struct ref *cpy = copy_ref(ref); @@ -2535,7 +2363,7 @@ static int get_stale_heads_cb(const char *refname, const char *referent UNUSED, memset(&query, 0, sizeof(struct refspec_item)); query.dst = (char *)refname; - query_refspecs_multiple(info->rs, &query, &matches); + refspec_find_all_matches(info->rs, &query, &matches); if (matches.nr == 0) goto clean_exit; /* No matches */ @@ -3003,3 +2831,13 @@ char *relative_url(const char *remote_url, const char *url, free(out); return strbuf_detach(&sb, NULL); } + +int valid_remote_name(const char *name) +{ + int result; + struct strbuf refspec = STRBUF_INIT; + strbuf_addf(&refspec, "refs/heads/test:refs/remotes/%s/test", name); + result = valid_fetch_refspec(refspec.buf); + strbuf_release(&refspec); + return result; +} @@ -21,8 +21,10 @@ struct transport_ls_refs_options; enum { REMOTE_UNCONFIGURED = 0, REMOTE_CONFIG, +#ifndef WITH_BREAKING_CHANGES REMOTE_REMOTES, REMOTE_BRANCHES +#endif /* WITH_BREAKING_CHANGES */ }; struct rewrite { @@ -219,6 +221,11 @@ struct ref *alloc_ref(const char *name); struct ref *copy_ref(const struct ref *ref); struct ref *copy_ref_list(const struct ref *ref); int count_refspec_match(const char *, struct ref *refs, struct ref **matched_ref); +/* + * Put a ref in the tail and prepare tail for adding another one. + * *tail is the pointer to the tail of the list of refs. + */ +void tail_link_ref(struct ref *ref, struct ref ***tail); int check_ref_type(const struct ref *ref, int flags); @@ -261,21 +268,6 @@ int resolve_remote_symref(struct ref *ref, struct ref *list); */ struct ref *ref_remove_duplicates(struct ref *ref_map); -/* - * Check whether a name matches any negative refspec in rs. Returns 1 if the - * name matches at least one negative refspec, and 0 otherwise. - */ -int omit_name_by_refspec(const char *name, struct refspec *rs); - -/* - * Remove all entries in the input list which match any negative refspec in - * the refspec list. - */ -struct ref *apply_negative_refspecs(struct ref *ref_map, struct refspec *rs); - -int query_refspecs(struct refspec *rs, struct refspec_item *query); -char *apply_refspecs(struct refspec *rs, const char *name); - int check_push_refs(struct ref *src, struct refspec *rs); int match_push_refs(struct ref *src, struct ref **dst, struct refspec *rs, int flags); @@ -461,4 +453,6 @@ void apply_push_cas(struct push_cas_option *, struct remote *, struct ref *); char *relative_url(const char *remote_url, const char *url, const char *up_path); +int valid_remote_name(const char *name); + #endif diff --git a/repo-settings.c b/repo-settings.c index 9d16d5399e..67e9cfd2e6 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -4,6 +4,7 @@ #include "repository.h" #include "midx.h" #include "pack-objects.h" +#include "setup.h" static void repo_cfg_bool(struct repository *r, const char *key, int *dest, int def) @@ -21,7 +22,6 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest, void prepare_repo_settings(struct repository *r) { - const struct repo_settings defaults = REPO_SETTINGS_INIT; int experimental; int value; const char *strval; @@ -35,7 +35,7 @@ void prepare_repo_settings(struct repository *r) if (r->settings.initialized) return; - memcpy(&r->settings, &defaults, sizeof(defaults)); + repo_settings_clear(r); r->settings.initialized++; /* Booleans config or default, cascades to other settings */ @@ -143,6 +143,14 @@ void prepare_repo_settings(struct repository *r) r->settings.packed_git_limit = ulongval; } +void repo_settings_clear(struct repository *r) +{ + struct repo_settings empty = REPO_SETTINGS_INIT; + FREE_AND_NULL(r->settings.fsmonitor); + FREE_AND_NULL(r->settings.hooks_path); + r->settings = empty; +} + enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo) { const char *value; @@ -167,3 +175,35 @@ int repo_settings_get_warn_ambiguous_refs(struct repository *repo) &repo->settings.warn_ambiguous_refs, 1); return repo->settings.warn_ambiguous_refs; } + +const char *repo_settings_get_hooks_path(struct repository *repo) +{ + if (!repo->settings.hooks_path) + repo_config_get_pathname(repo, "core.hookspath", &repo->settings.hooks_path); + return repo->settings.hooks_path; +} + +int repo_settings_get_shared_repository(struct repository *repo) +{ + if (!repo->settings.shared_repository_initialized) { + const char *var = "core.sharedrepository"; + const char *value; + if (!repo_config_get_value(repo, var, &value)) + repo->settings.shared_repository = git_config_perm(var, value); + else + repo->settings.shared_repository = PERM_UMASK; + repo->settings.shared_repository_initialized = 1; + } + return repo->settings.shared_repository; +} + +void repo_settings_set_shared_repository(struct repository *repo, int value) +{ + repo->settings.shared_repository = value; + repo->settings.shared_repository_initialized = 1; +} + +void repo_settings_reset_shared_repository(struct repository *repo) +{ + repo->settings.shared_repository_initialized = 0; +} diff --git a/repo-settings.h b/repo-settings.h index 93ea0c3274..ddc11967e0 100644 --- a/repo-settings.h +++ b/repo-settings.h @@ -37,6 +37,9 @@ struct repo_settings { int pack_use_bitmap_boundary_traversal; int pack_use_multi_pack_reuse; + int shared_repository; + int shared_repository_initialized; + /* * Does this repository have core.useReplaceRefs=true (on by * default)? This provides a repository-scoped version of this @@ -61,8 +64,11 @@ struct repo_settings { size_t delta_base_cache_limit; size_t packed_git_window_size; size_t packed_git_limit; + + char *hooks_path; }; #define REPO_SETTINGS_INIT { \ + .shared_repository = -1, \ .index_version = -1, \ .core_untracked_cache = UNTRACKED_CACHE_KEEP, \ .fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \ @@ -73,10 +79,18 @@ struct repo_settings { } void prepare_repo_settings(struct repository *r); +void repo_settings_clear(struct repository *r); /* Read the value for "core.logAllRefUpdates". */ enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo); /* Read the value for "core.warnAmbiguousRefs". */ int repo_settings_get_warn_ambiguous_refs(struct repository *repo); +/* Read the value for "core.hooksPath". */ +const char *repo_settings_get_hooks_path(struct repository *repo); + +/* Read, set or reset the value for "core.sharedRepository". */ +int repo_settings_get_shared_repository(struct repository *repo); +void repo_settings_set_shared_repository(struct repository *repo, int value); +void repo_settings_reset_shared_repository(struct repository *repo); #endif /* REPO_SETTINGS_H */ diff --git a/repository.c b/repository.c index 1a6a62bbd0..6cbaf2e3da 100644 --- a/repository.c +++ b/repository.c @@ -312,8 +312,8 @@ int repo_submodule_init(struct repository *subrepo, struct strbuf worktree = STRBUF_INIT; int ret = 0; - strbuf_repo_worktree_path(&gitdir, superproject, "%s/.git", path); - strbuf_repo_worktree_path(&worktree, superproject, "%s", path); + repo_worktree_path_append(superproject, &gitdir, "%s/.git", path); + repo_worktree_path_append(superproject, &worktree, "%s", path); if (repo_init(subrepo, gitdir.buf, worktree.buf)) { /* @@ -380,7 +380,7 @@ void repo_clear(struct repository *repo) parsed_object_pool_clear(repo->parsed_objects); FREE_AND_NULL(repo->parsed_objects); - FREE_AND_NULL(repo->settings.fsmonitor); + repo_settings_clear(repo); if (repo->config) { git_configset_clear(repo->config); @@ -91,16 +91,18 @@ static void assign_variant(struct rerere_id *id) id->variant = variant; } -const char *rerere_path(const struct rerere_id *id, const char *file) +const char *rerere_path(struct strbuf *buf, const struct rerere_id *id, const char *file) { if (!file) - return git_path("rr-cache/%s", rerere_id_hex(id)); + return repo_git_path_replace(the_repository, buf, "rr-cache/%s", + rerere_id_hex(id)); if (id->variant <= 0) - return git_path("rr-cache/%s/%s", rerere_id_hex(id), file); + return repo_git_path_replace(the_repository, buf, "rr-cache/%s/%s", + rerere_id_hex(id), file); - return git_path("rr-cache/%s/%s.%d", - rerere_id_hex(id), file, id->variant); + return repo_git_path_replace(the_repository, buf, "rr-cache/%s/%s.%d", + rerere_id_hex(id), file, id->variant); } static int is_rr_file(const char *name, const char *filename, int *variant) @@ -125,8 +127,12 @@ static int is_rr_file(const char *name, const char *filename, int *variant) static void scan_rerere_dir(struct rerere_dir *rr_dir) { struct dirent *de; - DIR *dir = opendir(git_path("rr-cache/%s", rr_dir->name)); + char *path; + DIR *dir; + path = repo_git_path(the_repository, "rr-cache/%s", rr_dir->name); + dir = opendir(path); + free(path); if (!dir) return; while ((de = readdir(dir)) != NULL) { @@ -358,7 +364,7 @@ static void rerere_strbuf_putconflict(struct strbuf *buf, int ch, size_t size) } static int handle_conflict(struct strbuf *out, struct rerere_io *io, - int marker_size, git_hash_ctx *ctx) + int marker_size, struct git_hash_ctx *ctx) { enum { RR_SIDE_1 = 0, RR_SIDE_2, RR_ORIGINAL @@ -396,12 +402,12 @@ static int handle_conflict(struct strbuf *out, struct rerere_io *io, strbuf_addbuf(out, &two); rerere_strbuf_putconflict(out, '>', marker_size); if (ctx) { - the_hash_algo->update_fn(ctx, one.buf ? - one.buf : "", - one.len + 1); - the_hash_algo->update_fn(ctx, two.buf ? - two.buf : "", - two.len + 1); + git_hash_update(ctx, one.buf ? + one.buf : "", + one.len + 1); + git_hash_update(ctx, two.buf ? + two.buf : "", + two.len + 1); } break; } else if (hunk == RR_SIDE_1) @@ -432,7 +438,7 @@ static int handle_conflict(struct strbuf *out, struct rerere_io *io, */ static int handle_path(unsigned char *hash, struct rerere_io *io, int marker_size) { - git_hash_ctx ctx; + struct git_hash_ctx ctx; struct strbuf buf = STRBUF_INIT, out = STRBUF_INIT; int has_conflicts = 0; if (hash) @@ -453,7 +459,7 @@ static int handle_path(unsigned char *hash, struct rerere_io *io, int marker_siz strbuf_release(&out); if (hash) - the_hash_algo->final_fn(hash, &ctx); + git_hash_final(hash, &ctx); return has_conflicts; } @@ -624,9 +630,10 @@ static int try_merge(struct index_state *istate, { enum ll_merge_result ret; mmfile_t base = {NULL, 0}, other = {NULL, 0}; + struct strbuf buf = STRBUF_INIT; - if (read_mmfile(&base, rerere_path(id, "preimage")) || - read_mmfile(&other, rerere_path(id, "postimage"))) { + if (read_mmfile(&base, rerere_path(&buf, id, "preimage")) || + read_mmfile(&other, rerere_path(&buf, id, "postimage"))) { ret = LL_MERGE_CONFLICT; } else { /* @@ -637,6 +644,7 @@ static int try_merge(struct index_state *istate, istate, NULL); } + strbuf_release(&buf); free(base.ptr); free(other.ptr); @@ -657,6 +665,7 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c { FILE *f; int ret; + struct strbuf buf = STRBUF_INIT; mmfile_t cur = {NULL, 0}; mmbuffer_t result = {NULL, 0}; @@ -664,8 +673,8 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c * Normalize the conflicts in path and write it out to * "thisimage" temporary file. */ - if ((handle_file(istate, path, NULL, rerere_path(id, "thisimage")) < 0) || - read_mmfile(&cur, rerere_path(id, "thisimage"))) { + if ((handle_file(istate, path, NULL, rerere_path(&buf, id, "thisimage")) < 0) || + read_mmfile(&cur, rerere_path(&buf, id, "thisimage"))) { ret = 1; goto out; } @@ -678,9 +687,9 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c * A successful replay of recorded resolution. * Mark that "postimage" was used to help gc. */ - if (utime(rerere_path(id, "postimage"), NULL) < 0) + if (utime(rerere_path(&buf, id, "postimage"), NULL) < 0) warning_errno(_("failed utime() on '%s'"), - rerere_path(id, "postimage")); + rerere_path(&buf, id, "postimage")); /* Update "path" with the resolution */ f = fopen(path, "w"); @@ -694,6 +703,7 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c out: free(cur.ptr); free(result.ptr); + strbuf_release(&buf); return ret; } @@ -720,9 +730,11 @@ static void update_paths(struct repository *r, struct string_list *update) static void remove_variant(struct rerere_id *id) { - unlink_or_warn(rerere_path(id, "postimage")); - unlink_or_warn(rerere_path(id, "preimage")); + struct strbuf buf = STRBUF_INIT; + unlink_or_warn(rerere_path(&buf, id, "postimage")); + unlink_or_warn(rerere_path(&buf, id, "preimage")); id->collection->status[id->variant] = 0; + strbuf_release(&buf); } /* @@ -739,6 +751,7 @@ static void do_rerere_one_path(struct index_state *istate, const char *path = rr_item->string; struct rerere_id *id = rr_item->util; struct rerere_dir *rr_dir = id->collection; + struct strbuf buf = STRBUF_INIT; int variant; variant = id->variant; @@ -746,12 +759,12 @@ static void do_rerere_one_path(struct index_state *istate, /* Has the user resolved it already? */ if (variant >= 0) { if (!handle_file(istate, path, NULL, NULL)) { - copy_file(rerere_path(id, "postimage"), path, 0666); + copy_file(rerere_path(&buf, id, "postimage"), path, 0666); id->collection->status[variant] |= RR_HAS_POSTIMAGE; fprintf_ln(stderr, _("Recorded resolution for '%s'."), path); free_rerere_id(rr_item); rr_item->util = NULL; - return; + goto out; } /* * There may be other variants that can cleanly @@ -787,22 +800,25 @@ static void do_rerere_one_path(struct index_state *istate, path); free_rerere_id(rr_item); rr_item->util = NULL; - return; + goto out; } /* None of the existing one applies; we need a new variant */ assign_variant(id); variant = id->variant; - handle_file(istate, path, NULL, rerere_path(id, "preimage")); + handle_file(istate, path, NULL, rerere_path(&buf, id, "preimage")); if (id->collection->status[variant] & RR_HAS_POSTIMAGE) { - const char *path = rerere_path(id, "postimage"); + const char *path = rerere_path(&buf, id, "postimage"); if (unlink(path)) die_errno(_("cannot unlink stray '%s'"), path); id->collection->status[variant] &= ~RR_HAS_POSTIMAGE; } id->collection->status[variant] |= RR_HAS_PREIMAGE; fprintf_ln(stderr, _("Recorded preimage for '%s'"), path); + +out: + strbuf_release(&buf); } static int do_plain_rerere(struct repository *r, @@ -810,6 +826,7 @@ static int do_plain_rerere(struct repository *r, { struct string_list conflict = STRING_LIST_INIT_DUP; struct string_list update = STRING_LIST_INIT_DUP; + struct strbuf buf = STRBUF_INIT; int i; find_conflict(r, &conflict); @@ -843,7 +860,7 @@ static int do_plain_rerere(struct repository *r, string_list_insert(rr, path)->util = id; /* Ensure that the directory exists. */ - mkdir_in_gitdir(rerere_path(id, NULL)); + mkdir_in_gitdir(rerere_path(&buf, id, NULL)); } for (i = 0; i < rr->nr; i++) @@ -854,6 +871,7 @@ static int do_plain_rerere(struct repository *r, string_list_clear(&conflict, 0); string_list_clear(&update, 0); + strbuf_release(&buf); return write_rr(rr, fd); } @@ -1033,6 +1051,7 @@ static int rerere_forget_one_path(struct index_state *istate, struct rerere_id *id; unsigned char hash[GIT_MAX_RAWSZ]; int ret; + struct strbuf buf = STRBUF_INIT; struct string_list_item *item; /* @@ -1056,8 +1075,8 @@ static int rerere_forget_one_path(struct index_state *istate, if (!has_rerere_resolution(id)) continue; - handle_cache(istate, path, hash, rerere_path(id, "thisimage")); - if (read_mmfile(&cur, rerere_path(id, "thisimage"))) { + handle_cache(istate, path, hash, rerere_path(&buf, id, "thisimage")); + if (read_mmfile(&cur, rerere_path(&buf, id, "thisimage"))) { free(cur.ptr); error(_("failed to update conflicted state in '%s'"), path); goto fail_exit; @@ -1074,7 +1093,7 @@ static int rerere_forget_one_path(struct index_state *istate, goto fail_exit; } - filename = rerere_path(id, "postimage"); + filename = rerere_path(&buf, id, "postimage"); if (unlink(filename)) { if (errno == ENOENT) error(_("no remembered resolution for '%s'"), path); @@ -1088,7 +1107,7 @@ static int rerere_forget_one_path(struct index_state *istate, * conflict in the working tree, run us again to record * the postimage. */ - handle_cache(istate, path, hash, rerere_path(id, "preimage")); + handle_cache(istate, path, hash, rerere_path(&buf, id, "preimage")); fprintf_ln(stderr, _("Updated preimage for '%s'"), path); /* @@ -1099,9 +1118,11 @@ static int rerere_forget_one_path(struct index_state *istate, free_rerere_id(item); item->util = id; fprintf(stderr, _("Forgot resolution for '%s'\n"), path); + strbuf_release(&buf); return 0; fail_exit: + strbuf_release(&buf); free(id); return -1; } @@ -1147,16 +1168,26 @@ int rerere_forget(struct repository *r, struct pathspec *pathspec) static timestamp_t rerere_created_at(struct rerere_id *id) { + struct strbuf buf = STRBUF_INIT; struct stat st; + timestamp_t ret; + + ret = stat(rerere_path(&buf, id, "preimage"), &st) ? (time_t) 0 : st.st_mtime; - return stat(rerere_path(id, "preimage"), &st) ? (time_t) 0 : st.st_mtime; + strbuf_release(&buf); + return ret; } static timestamp_t rerere_last_used_at(struct rerere_id *id) { + struct strbuf buf = STRBUF_INIT; struct stat st; + timestamp_t ret; + + ret = stat(rerere_path(&buf, id, "postimage"), &st) ? (time_t) 0 : st.st_mtime; - return stat(rerere_path(id, "postimage"), &st) ? (time_t) 0 : st.st_mtime; + strbuf_release(&buf); + return ret; } /* @@ -1164,9 +1195,11 @@ static timestamp_t rerere_last_used_at(struct rerere_id *id) */ static void unlink_rr_item(struct rerere_id *id) { - unlink_or_warn(rerere_path(id, "thisimage")); + struct strbuf buf = STRBUF_INIT; + unlink_or_warn(rerere_path(&buf, id, "thisimage")); remove_variant(id); id->collection->status[id->variant] = 0; + strbuf_release(&buf); } static void prune_one(struct rerere_id *id, @@ -1205,6 +1238,7 @@ void rerere_gc(struct repository *r, struct string_list *rr) timestamp_t now = time(NULL); timestamp_t cutoff_noresolve = now - 15 * 86400; timestamp_t cutoff_resolve = now - 60 * 86400; + struct strbuf buf = STRBUF_INIT; if (setup_rerere(r, rr, 0) < 0) return; @@ -1214,7 +1248,7 @@ void rerere_gc(struct repository *r, struct string_list *rr) repo_config_get_expiry_in_days(the_repository, "gc.rerereunresolved", &cutoff_noresolve, now); git_config(git_default_config, NULL); - dir = opendir(git_path("rr-cache")); + dir = opendir(repo_git_path_replace(the_repository, &buf, "rr-cache")); if (!dir) die_errno(_("unable to open rr-cache directory")); /* Collect stale conflict IDs ... */ @@ -1243,9 +1277,12 @@ void rerere_gc(struct repository *r, struct string_list *rr) /* ... and then remove the empty directories */ for (i = 0; i < to_remove.nr; i++) - rmdir(git_path("rr-cache/%s", to_remove.items[i].string)); + rmdir(repo_git_path_replace(the_repository, &buf, + "rr-cache/%s", to_remove.items[i].string)); + string_list_clear(&to_remove, 0); rollback_lock_file(&write_lock); + strbuf_release(&buf); } /* @@ -1264,10 +1301,14 @@ void rerere_clear(struct repository *r, struct string_list *merge_rr) for (i = 0; i < merge_rr->nr; i++) { struct rerere_id *id = merge_rr->items[i].util; + struct strbuf buf = STRBUF_INIT; + if (!has_rerere_resolution(id)) { unlink_rr_item(id); - rmdir(rerere_path(id, NULL)); + rmdir(rerere_path(&buf, id, NULL)); } + + strbuf_release(&buf); } unlink_or_warn(git_path_merge_rr(r)); rollback_lock_file(&write_lock); @@ -32,7 +32,8 @@ int repo_rerere(struct repository *, int); * path to that filesystem entity. With "file" specified with NULL, * return the path to the directory that houses these files. */ -const char *rerere_path(const struct rerere_id *, const char *file); +const char *rerere_path(struct strbuf *buf, const struct rerere_id *, + const char *file); int rerere_forget(struct repository *, struct pathspec *); int rerere_remaining(struct repository *, struct string_list *); void rerere_clear(struct repository *, struct string_list *); diff --git a/resolve-undo.c b/resolve-undo.c index b5a9dfb4ac..52c45e5a49 100644 --- a/resolve-undo.c +++ b/resolve-undo.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -34,7 +33,8 @@ void record_resolve_undo(struct index_state *istate, struct cache_entry *ce) ui->mode[stage - 1] = ce->ce_mode; } -void resolve_undo_write(struct strbuf *sb, struct string_list *resolve_undo) +void resolve_undo_write(struct strbuf *sb, struct string_list *resolve_undo, + const struct git_hash_algo *algop) { struct string_list_item *item; for_each_string_list_item(item, resolve_undo) { @@ -50,18 +50,19 @@ void resolve_undo_write(struct strbuf *sb, struct string_list *resolve_undo) for (i = 0; i < 3; i++) { if (!ui->mode[i]) continue; - strbuf_add(sb, ui->oid[i].hash, the_hash_algo->rawsz); + strbuf_add(sb, ui->oid[i].hash, algop->rawsz); } } } -struct string_list *resolve_undo_read(const char *data, unsigned long size) +struct string_list *resolve_undo_read(const char *data, unsigned long size, + const struct git_hash_algo *algop) { struct string_list *resolve_undo; size_t len; char *endptr; int i; - const unsigned rawsz = the_hash_algo->rawsz; + const unsigned rawsz = algop->rawsz; CALLOC_ARRAY(resolve_undo, 1); resolve_undo->strdup_strings = 1; @@ -96,8 +97,7 @@ struct string_list *resolve_undo_read(const char *data, unsigned long size) continue; if (size < rawsz) goto error; - oidread(&ui->oid[i], (const unsigned char *)data, - the_repository->hash_algo); + oidread(&ui->oid[i], (const unsigned char *)data, algop); size -= rawsz; data += rawsz; } diff --git a/resolve-undo.h b/resolve-undo.h index 89a3227262..7ed11a1c59 100644 --- a/resolve-undo.h +++ b/resolve-undo.h @@ -14,8 +14,10 @@ struct resolve_undo_info { }; void record_resolve_undo(struct index_state *, struct cache_entry *); -void resolve_undo_write(struct strbuf *, struct string_list *); -struct string_list *resolve_undo_read(const char *, unsigned long); +void resolve_undo_write(struct strbuf *, struct string_list *, + const struct git_hash_algo *algop); +struct string_list *resolve_undo_read(const char *, unsigned long, + const struct git_hash_algo *algop); void resolve_undo_clear_index(struct index_state *); int unmerge_index_entry(struct index_state *, const char *, struct resolve_undo_info *, unsigned); void unmerge_index(struct index_state *, const struct pathspec *, unsigned); diff --git a/revision.c b/revision.c index 474fa1e767..c4390f0938 100644 --- a/revision.c +++ b/revision.c @@ -1874,15 +1874,20 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags) for (p = worktrees; *p; p++) { struct worktree *wt = *p; struct index_state istate = INDEX_STATE_INIT(revs->repo); + char *wt_gitdir; if (wt->is_current) continue; /* current index already taken care of */ + wt_gitdir = get_worktree_git_dir(wt); + if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"), - get_worktree_git_dir(wt)) > 0) + wt_gitdir) > 0) do_add_index_objects_to_pending(revs, &istate, flags); + discard_index(&istate); + free(wt_gitdir); } free_worktrees(worktrees); } @@ -409,6 +409,7 @@ void load_builtin_commands(const char *prefix UNUSED, static int cmd_clone(int argc, const char **argv) { const char *branch = NULL; + char *branch_to_free = NULL; int full_clone = 0, single_branch = 0, show_progress = isatty(2); int src = 1, tags = 1; struct option clone_options[] = { @@ -490,7 +491,7 @@ static int cmd_clone(int argc, const char **argv) /* common-main already logs `argv` */ trace2_def_repo(the_repository); - if (!branch && !(branch = remote_default_branch(url))) { + if (!branch && !(branch = branch_to_free = remote_default_branch(url))) { res = error(_("failed to get default branch for '%s'"), url); goto cleanup; } @@ -552,6 +553,7 @@ static int cmd_clone(int argc, const char **argv) res = register_dir(); cleanup: + free(branch_to_free); free(enlistment); free(dir); strbuf_release(&buf); diff --git a/send-pack.c b/send-pack.c index 7e83213683..856a65d5f5 100644 --- a/send-pack.c +++ b/send-pack.c @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "config.h" #include "commit.h" @@ -44,10 +42,11 @@ int option_parse_push_signed(const struct option *opt, die("bad %s argument: %s", opt->long_name, arg); } -static void feed_object(const struct object_id *oid, FILE *fh, int negative) +static void feed_object(struct repository *r, + const struct object_id *oid, FILE *fh, int negative) { if (negative && - !repo_has_object_file_with_flags(the_repository, oid, + !repo_has_object_file_with_flags(r, oid, OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK)) return; @@ -61,7 +60,8 @@ static void feed_object(const struct object_id *oid, FILE *fh, int negative) /* * Make a pack stream and spit it out into file descriptor fd */ -static int pack_objects(int fd, struct ref *refs, struct oid_array *advertised, +static int pack_objects(struct repository *r, + int fd, struct ref *refs, struct oid_array *advertised, struct oid_array *negotiated, struct send_pack_args *args) { @@ -74,7 +74,7 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *advertised, FILE *po_in; int rc; - trace2_region_enter("send_pack", "pack_objects", the_repository); + trace2_region_enter("send_pack", "pack_objects", r); strvec_push(&po.args, "pack-objects"); strvec_push(&po.args, "--all-progress-implied"); strvec_push(&po.args, "--revs"); @@ -87,7 +87,7 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *advertised, strvec_push(&po.args, "-q"); if (args->progress) strvec_push(&po.args, "--progress"); - if (is_repository_shallow(the_repository)) + if (is_repository_shallow(r)) strvec_push(&po.args, "--shallow"); if (args->disable_bitmaps) strvec_push(&po.args, "--no-use-bitmap-index"); @@ -104,15 +104,15 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *advertised, */ po_in = xfdopen(po.in, "w"); for (size_t i = 0; i < advertised->nr; i++) - feed_object(&advertised->oid[i], po_in, 1); + feed_object(r, &advertised->oid[i], po_in, 1); for (size_t i = 0; i < negotiated->nr; i++) - feed_object(&negotiated->oid[i], po_in, 1); + feed_object(r, &negotiated->oid[i], po_in, 1); while (refs) { if (!is_null_oid(&refs->old_oid)) - feed_object(&refs->old_oid, po_in, 1); + feed_object(r, &refs->old_oid, po_in, 1); if (!is_null_oid(&refs->new_oid)) - feed_object(&refs->new_oid, po_in, 0); + feed_object(r, &refs->new_oid, po_in, 0); refs = refs->next; } @@ -146,10 +146,10 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *advertised, */ if (rc > 128 && rc != 141) error("pack-objects died of signal %d", rc - 128); - trace2_region_leave("send_pack", "pack_objects", the_repository); + trace2_region_leave("send_pack", "pack_objects", r); return -1; } - trace2_region_leave("send_pack", "pack_objects", the_repository); + trace2_region_leave("send_pack", "pack_objects", r); return 0; } @@ -164,7 +164,8 @@ static int receive_unpack_status(struct packet_reader *reader) return 0; } -static int receive_status(struct packet_reader *reader, struct ref *refs) +static int receive_status(struct repository *r, + struct packet_reader *reader, struct ref *refs) { struct ref *hint; int ret; @@ -172,7 +173,7 @@ static int receive_status(struct packet_reader *reader, struct ref *refs) int new_report = 0; int once = 0; - trace2_region_enter("send_pack", "receive_status", the_repository); + trace2_region_enter("send_pack", "receive_status", r); hint = NULL; ret = receive_unpack_status(reader); while (1) { @@ -221,10 +222,10 @@ static int receive_status(struct packet_reader *reader, struct ref *refs) if (!strcmp(key, "refname")) report->ref_name = xstrdup_or_null(val); else if (!strcmp(key, "old-oid") && val && - !parse_oid_hex(val, &old_oid, &val)) + !parse_oid_hex_algop(val, &old_oid, &val, r->hash_algo)) report->old_oid = oiddup(&old_oid); else if (!strcmp(key, "new-oid") && val && - !parse_oid_hex(val, &new_oid, &val)) + !parse_oid_hex_algop(val, &new_oid, &val, r->hash_algo)) report->new_oid = oiddup(&new_oid); else if (!strcmp(key, "forced-update")) report->forced_update = 1; @@ -271,7 +272,7 @@ static int receive_status(struct packet_reader *reader, struct ref *refs) new_report = 1; } } - trace2_region_leave("send_pack", "receive_status", the_repository); + trace2_region_leave("send_pack", "receive_status", r); return ret; } @@ -293,9 +294,9 @@ static int advertise_shallow_grafts_cb(const struct commit_graft *graft, void *c return 0; } -static void advertise_shallow_grafts_buf(struct strbuf *sb) +static void advertise_shallow_grafts_buf(struct repository *r, struct strbuf *sb) { - if (!is_repository_shallow(the_repository)) + if (!is_repository_shallow(r)) return; for_each_commit_graft(advertise_shallow_grafts_cb, sb); } @@ -426,13 +427,14 @@ static void reject_invalid_nonce(const char *nonce, int len) } } -static void get_commons_through_negotiation(const char *url, +static void get_commons_through_negotiation(struct repository *r, + const char *url, const struct ref *remote_refs, struct oid_array *commons) { struct child_process child = CHILD_PROCESS_INIT; const struct ref *ref; - int len = the_hash_algo->hexsz + 1; /* hash + NL */ + int len = r->hash_algo->hexsz + 1; /* hash + NL */ int nr_negotiation_tip = 0; child.git_cmd = 1; @@ -466,7 +468,7 @@ static void get_commons_through_negotiation(const char *url, break; if (read_len != len) die("invalid length read %d", read_len); - if (parse_oid_hex(hex_hash, &oid, &end) || *end != '\n') + if (parse_oid_hex_algop(hex_hash, &oid, &end, r->hash_algo) || *end != '\n') die("invalid hash"); oid_array_append(commons, &oid); } while (1); @@ -480,7 +482,8 @@ static void get_commons_through_negotiation(const char *url, } } -int send_pack(struct send_pack_args *args, +int send_pack(struct repository *r, + struct send_pack_args *args, int fd[], struct child_process *conn, struct ref *remote_refs, struct oid_array *extra_have) @@ -518,17 +521,17 @@ int send_pack(struct send_pack_args *args, goto out; } - git_config_get_bool("push.negotiate", &push_negotiate); + repo_config_get_bool(r, "push.negotiate", &push_negotiate); if (push_negotiate) { - trace2_region_enter("send_pack", "push_negotiate", the_repository); - get_commons_through_negotiation(args->url, remote_refs, &commons); - trace2_region_leave("send_pack", "push_negotiate", the_repository); + trace2_region_enter("send_pack", "push_negotiate", r); + get_commons_through_negotiation(r, args->url, remote_refs, &commons); + trace2_region_leave("send_pack", "push_negotiate", r); } - if (!git_config_get_bool("push.usebitmaps", &use_bitmaps)) + if (!repo_config_get_bool(r, "push.usebitmaps", &use_bitmaps)) args->disable_bitmaps = !use_bitmaps; - git_config_get_bool("transfer.advertisesid", &advertise_sid); + repo_config_get_bool(r, "transfer.advertisesid", &advertise_sid); /* Does the other end support the reporting? */ if (server_supports("report-status-v2")) @@ -554,7 +557,7 @@ int send_pack(struct send_pack_args *args, if (server_supports("push-options")) push_options_supported = 1; - if (!server_supports_hash(the_hash_algo->name, &object_format_supported)) + if (!server_supports_hash(r->hash_algo->name, &object_format_supported)) die(_("the receiving end does not support this repository's hash algorithm")); if (args->push_cert != SEND_PACK_PUSH_CERT_NEVER) { @@ -596,7 +599,7 @@ int send_pack(struct send_pack_args *args, if (use_push_options) strbuf_addstr(&cap_buf, " push-options"); if (object_format_supported) - strbuf_addf(&cap_buf, " object-format=%s", the_hash_algo->name); + strbuf_addf(&cap_buf, " object-format=%s", r->hash_algo->name); if (agent_supported) strbuf_addf(&cap_buf, " agent=%s", git_user_agent_sanitized()); if (advertise_sid) @@ -629,7 +632,8 @@ int send_pack(struct send_pack_args *args, reject_atomic_push(remote_refs, args->send_mirror); error("atomic push failed for ref %s. status: %d", ref->name, ref->status); - ret = args->porcelain ? 0 : -1; + ret = ERROR_SEND_PACK_BAD_REF_STATUS; + packet_flush(out); goto out; } /* else fallthrough */ @@ -646,7 +650,7 @@ int send_pack(struct send_pack_args *args, } if (!args->dry_run) - advertise_shallow_grafts_buf(&req_buf); + advertise_shallow_grafts_buf(r, &req_buf); /* * Finally, tell the other end! @@ -686,7 +690,7 @@ int send_pack(struct send_pack_args *args, } if (args->stateless_rpc) { - if (!args->dry_run && (cmds_sent || is_repository_shallow(the_repository))) { + if (!args->dry_run && (cmds_sent || is_repository_shallow(r))) { packet_buf_flush(&req_buf); send_sideband(out, -1, req_buf.buf, req_buf.len, LARGE_PACKET_MAX); } @@ -711,7 +715,7 @@ int send_pack(struct send_pack_args *args, PACKET_READ_DIE_ON_ERR_PACKET); if (need_pack_data && cmds_sent) { - if (pack_objects(out, remote_refs, extra_have, &commons, args) < 0) { + if (pack_objects(r, out, remote_refs, extra_have, &commons, args) < 0) { if (args->stateless_rpc) close(out); if (git_connection_is_socket(conn)) @@ -724,7 +728,7 @@ int send_pack(struct send_pack_args *args, * we get one). */ if (status_report) - receive_status(&reader, remote_refs); + receive_status(r, &reader, remote_refs); if (use_sideband) { close(demux.out); @@ -743,7 +747,7 @@ int send_pack(struct send_pack_args *args, packet_flush(out); if (status_report && cmds_sent) - ret = receive_status(&reader, remote_refs); + ret = receive_status(r, &reader, remote_refs); else ret = 0; if (args->stateless_rpc) @@ -760,11 +764,6 @@ int send_pack(struct send_pack_args *args, if (ret < 0) goto out; - if (args->porcelain) { - ret = 0; - goto out; - } - for (ref = remote_refs; ref; ref = ref->next) { switch (ref->status) { case REF_STATUS_NONE: @@ -772,7 +771,7 @@ int send_pack(struct send_pack_args *args, case REF_STATUS_OK: break; default: - ret = -1; + ret = ERROR_SEND_PACK_BAD_REF_STATUS; goto out; } } diff --git a/send-pack.h b/send-pack.h index 7edb80596c..c5ded2d200 100644 --- a/send-pack.h +++ b/send-pack.h @@ -6,12 +6,16 @@ struct child_process; struct oid_array; struct ref; +struct repository; /* Possible values for push_cert field in send_pack_args. */ #define SEND_PACK_PUSH_CERT_NEVER 0 #define SEND_PACK_PUSH_CERT_IF_ASKED 1 #define SEND_PACK_PUSH_CERT_ALWAYS 2 +/* At least one reference has been rejected by the remote side. */ +#define ERROR_SEND_PACK_BAD_REF_STATUS 1 + struct send_pack_args { const char *url; unsigned verbose:1, @@ -35,7 +39,17 @@ struct option; int option_parse_push_signed(const struct option *opt, const char *arg, int unset); -int send_pack(struct send_pack_args *args, +/* + * Compute a packfile and write it to a file descriptor. The `fd` array needs + * to contain two file descriptors: `fd[0]` is the file descriptor used as + * input for the packet reader, whereas `fd[1]` is the file descriptor the + * packfile will be written to. + * + * Returns 0 on success, non-zero otherwise. Negative return values indicate a + * generic error, whereas positive return values indicate specific error + * conditions as documented with the `ERROR_SEND_PACK_*` constants. + */ +int send_pack(struct repository *r, struct send_pack_args *args, int fd[], struct child_process *conn, struct ref *remote_refs, struct oid_array *extra_have); diff --git a/sequencer.c b/sequencer.c index 407ee4e90f..ad0ab75c8d 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2510,9 +2510,15 @@ static int do_pick_commit(struct repository *r, *check_todo = !!(flags & EDIT_MSG); if (!res && reword) { fast_forward_edit: - res = run_git_commit(NULL, opts, EDIT_MSG | - VERIFY_MSG | AMEND_MSG | - (flags & ALLOW_EMPTY)); + /* + * To reword we amend the commit we just + * picked or fast-forwarded. As the commit has + * already been picked we want to use the same + * set of commit flags regardless of how we + * got here. + */ + flags = EDIT_MSG | VERIFY_MSG | AMEND_MSG | ALLOW_EMPTY; + res = run_git_commit(NULL, opts, flags); *check_todo = 1; } } @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "repository.h" #include "config.h" @@ -12,6 +10,7 @@ #include "upload-pack.h" #include "bundle-uri.h" #include "trace2.h" +#include "promisor-remote.h" static int advertise_sid = -1; static int advertise_object_info = -1; @@ -31,6 +30,26 @@ static int agent_advertise(struct repository *r UNUSED, return 1; } +static int promisor_remote_advertise(struct repository *r, + struct strbuf *value) +{ + if (value) { + char *info = promisor_remote_info(r); + if (!info) + return 0; + strbuf_addstr(value, info); + free(info); + } + return 1; +} + +static void promisor_remote_receive(struct repository *r, + const char *remotes) +{ + mark_promisor_remotes_as_accepted(r, remotes); +} + + static int object_format_advertise(struct repository *r, struct strbuf *value) { @@ -157,9 +176,14 @@ static struct protocol_capability capabilities[] = { .advertise = bundle_uri_advertise, .command = bundle_uri_command, }, + { + .name = "promisor-remote", + .advertise = promisor_remote_advertise, + .receive = promisor_remote_receive, + }, }; -void protocol_v2_advertise_capabilities(void) +void protocol_v2_advertise_capabilities(struct repository *r) { struct strbuf capability = STRBUF_INIT; struct strbuf value = STRBUF_INIT; @@ -170,7 +194,7 @@ void protocol_v2_advertise_capabilities(void) for (size_t i = 0; i < ARRAY_SIZE(capabilities); i++) { struct protocol_capability *c = &capabilities[i]; - if (c->advertise(the_repository, &value)) { + if (c->advertise(r, &value)) { strbuf_addstr(&capability, c->name); if (value.len) { @@ -214,20 +238,20 @@ static struct protocol_capability *get_capability(const char *key, const char ** return NULL; } -static int receive_client_capability(const char *key) +static int receive_client_capability(struct repository *r, const char *key) { const char *value; const struct protocol_capability *c = get_capability(key, &value); - if (!c || c->command || !c->advertise(the_repository, NULL)) + if (!c || c->command || !c->advertise(r, NULL)) return 0; if (c->receive) - c->receive(the_repository, value); + c->receive(r, value); return 1; } -static int parse_command(const char *key, struct protocol_capability **command) +static int parse_command(struct repository *r, const char *key, struct protocol_capability **command) { const char *out; @@ -238,7 +262,7 @@ static int parse_command(const char *key, struct protocol_capability **command) if (*command) die("command '%s' requested after already requesting command '%s'", out, (*command)->name); - if (!cmd || !cmd->advertise(the_repository, NULL) || !cmd->command || value) + if (!cmd || !cmd->advertise(r, NULL) || !cmd->command || value) die("invalid command '%s'", out); *command = cmd; @@ -253,7 +277,7 @@ enum request_state { PROCESS_REQUEST_DONE, }; -static int process_request(void) +static int process_request(struct repository *r) { enum request_state state = PROCESS_REQUEST_KEYS; struct packet_reader reader; @@ -278,8 +302,8 @@ static int process_request(void) case PACKET_READ_EOF: BUG("Should have already died when seeing EOF"); case PACKET_READ_NORMAL: - if (parse_command(reader.line, &command) || - receive_client_capability(reader.line)) + if (parse_command(r, reader.line, &command) || + receive_client_capability(r, reader.line)) seen_capability_or_command = 1; else die("unknown capability '%s'", reader.line); @@ -319,30 +343,30 @@ static int process_request(void) if (!command) die("no command requested"); - if (client_hash_algo != hash_algo_by_ptr(the_repository->hash_algo)) + if (client_hash_algo != hash_algo_by_ptr(r->hash_algo)) die("mismatched object format: server %s; client %s", - the_repository->hash_algo->name, + r->hash_algo->name, hash_algos[client_hash_algo].name); - command->command(the_repository, &reader); + command->command(r, &reader); return 0; } -void protocol_v2_serve_loop(int stateless_rpc) +void protocol_v2_serve_loop(struct repository *r, int stateless_rpc) { if (!stateless_rpc) - protocol_v2_advertise_capabilities(); + protocol_v2_advertise_capabilities(r); /* * If stateless-rpc was requested then exit after * a single request/response exchange */ if (stateless_rpc) { - process_request(); + process_request(r); } else { for (;;) - if (process_request()) + if (process_request(r)) break; } } @@ -1,7 +1,9 @@ #ifndef SERVE_H #define SERVE_H -void protocol_v2_advertise_capabilities(void); -void protocol_v2_serve_loop(int stateless_rpc); +struct repository; + +void protocol_v2_advertise_capabilities(struct repository *r); +void protocol_v2_serve_loop(struct repository *r, int stateless_rpc); #endif /* SERVE_H */ diff --git a/server-info.c b/server-info.c index ef2f3f4b5c..1ca0e00d51 100644 --- a/server-info.c +++ b/server-info.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -18,6 +17,7 @@ #include "tempfile.h" struct update_info_ctx { + struct repository *repo; FILE *cur_fp; FILE *old_fp; /* becomes NULL if it differs from cur_fp */ struct strbuf cur_sb; @@ -73,7 +73,7 @@ static int uic_printf(struct update_info_ctx *uic, const char *fmt, ...) * it into place. The contents of the file come from "generate", which * should return non-zero if it encounters an error. */ -static int update_info_file(char *path, +static int update_info_file(struct repository *r, char *path, int (*generate)(struct update_info_ctx *), int force) { @@ -81,6 +81,7 @@ static int update_info_file(char *path, struct tempfile *f = NULL; int ret = -1; struct update_info_ctx uic = { + .repo = r, .cur_fp = NULL, .old_fp = NULL, .cur_sb = STRBUF_INIT, @@ -124,7 +125,7 @@ static int update_info_file(char *path, uic.cur_fp = NULL; if (uic_is_stale(&uic)) { - if (adjust_shared_perm(get_tempfile_path(f)) < 0) + if (adjust_shared_perm(r, get_tempfile_path(f)) < 0) goto out; if (rename_tempfile(&f, path) < 0) goto out; @@ -152,7 +153,7 @@ static int add_info_ref(const char *path, const char *referent UNUSED, const str void *cb_data) { struct update_info_ctx *uic = cb_data; - struct object *o = parse_object(the_repository, oid); + struct object *o = parse_object(uic->repo, oid); if (!o) return -1; @@ -160,7 +161,7 @@ static int add_info_ref(const char *path, const char *referent UNUSED, const str return -1; if (o->type == OBJ_TAG) { - o = deref_tag(the_repository, o, path, 0); + o = deref_tag(uic->repo, o, path, 0); if (o) if (uic_printf(uic, "%s %s^{}\n", oid_to_hex(&o->oid), path) < 0) @@ -171,14 +172,14 @@ static int add_info_ref(const char *path, const char *referent UNUSED, const str static int generate_info_refs(struct update_info_ctx *uic) { - return refs_for_each_ref(get_main_ref_store(the_repository), + return refs_for_each_ref(get_main_ref_store(uic->repo), add_info_ref, uic); } -static int update_info_refs(int force) +static int update_info_refs(struct repository *r, int force) { - char *path = git_pathdup("info/refs"); - int ret = update_info_file(path, generate_info_refs, force); + char *path = repo_git_path(r, "info/refs"); + int ret = update_info_file(r, path, generate_info_refs, force); free(path); return ret; } @@ -284,14 +285,14 @@ static int compare_info(const void *a_, const void *b_) return 1; } -static void init_pack_info(const char *infofile, int force) +static void init_pack_info(struct repository *r, const char *infofile, int force) { struct packed_git *p; int stale; int i; size_t alloc = 0; - for (p = get_all_packs(the_repository); p; p = p->next) { + for (p = get_all_packs(r); p; p = p->next) { /* we ignore things on alternate path since they are * not available to the pullers in general. */ @@ -340,33 +341,36 @@ static int write_pack_info_file(struct update_info_ctx *uic) return 0; } -static int update_info_packs(int force) +static int update_info_packs(struct repository *r, int force) { char *infofile = mkpathdup("%s/info/packs", - repo_get_object_directory(the_repository)); + repo_get_object_directory(r)); int ret; - init_pack_info(infofile, force); - ret = update_info_file(infofile, write_pack_info_file, force); + init_pack_info(r, infofile, force); + ret = update_info_file(r, infofile, write_pack_info_file, force); free_pack_info(); free(infofile); return ret; } /* public */ -int update_server_info(int force) +int update_server_info(struct repository *r, int force) { /* We would add more dumb-server support files later, * including index of available pack files and their * intended audiences. */ int errs = 0; + char *path; - errs = errs | update_info_refs(force); - errs = errs | update_info_packs(force); + errs = errs | update_info_refs(r, force); + errs = errs | update_info_packs(r, force); /* remove leftover rev-cache file if there is any */ - unlink_or_warn(git_path("info/rev-cache")); + path = repo_git_path(r, "info/rev-cache"); + unlink_or_warn(path); + free(path); return errs; } diff --git a/server-info.h b/server-info.h index 13bbde2c55..e634d1722b 100644 --- a/server-info.h +++ b/server-info.h @@ -1,7 +1,9 @@ #ifndef SERVER_INFO_H #define SERVER_INFO_H +struct repository; + /* Dumb servers support */ -int update_server_info(int); +int update_server_info(struct repository *r, int force); #endif /* SERVER_INFO_H */ @@ -792,7 +792,7 @@ int upgrade_repository_format(int target_version) struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT; int ret; - strbuf_git_common_path(&sb, the_repository, "config"); + repo_common_path_append(the_repository, &sb, "config"); read_repository_format(&repo_fmt, sb.buf); strbuf_release(&sb); @@ -1822,7 +1822,7 @@ const char *setup_git_directory_gently(int *nongit_ok) * * Regardless of the state of nongit_ok, startup_info->prefix and * the GIT_PREFIX environment variable must always match. For details - * see Documentation/config/alias.txt. + * see Documentation/config/alias.adoc. */ if (nongit_ok && *nongit_ok) startup_info->have_repository = 0; @@ -2088,7 +2088,7 @@ static void copy_templates_1(struct strbuf *path, struct strbuf *template_path, * with the way the namespace under .git/ is organized, should * be really carefully chosen. */ - safe_create_dir(path->buf, 1); + safe_create_dir(the_repository, path->buf, 1); while ((de = readdir(dir)) != NULL) { struct stat st_git, st_template; int exists = 0; @@ -2242,7 +2242,7 @@ void initialize_repository_version(int hash_algo, struct strbuf config = STRBUF_INIT; struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT; - strbuf_git_common_path(&config, the_repository, "config"); + repo_common_path_append(the_repository, &config, "config"); read_repository_format(&repo_fmt, config.buf); if (repo_fmt.v1_only_extensions.nr) @@ -2264,7 +2264,7 @@ static int is_reinit(void) char junk[2]; int ret; - git_path_buf(&buf, "HEAD"); + repo_git_path_replace(the_repository, &buf, "HEAD"); ret = !access(buf.buf, R_OK) || readlink(buf.buf, junk, sizeof(junk) - 1) != -1; strbuf_release(&buf); return ret; @@ -2316,8 +2316,7 @@ static int create_default_files(const char *template_path, int init_shared_repository) { struct stat st1; - struct strbuf buf = STRBUF_INIT; - char *path; + struct strbuf path = STRBUF_INIT; int reinit; int filemode; const char *work_tree = repo_get_work_tree(the_repository); @@ -2333,7 +2332,7 @@ static int create_default_files(const char *template_path, */ copy_templates(template_path); git_config_clear(); - reset_shared_repository(); + repo_settings_reset_shared_repository(the_repository); git_config(git_default_config, NULL); reinit = is_reinit(); @@ -2343,7 +2342,8 @@ static int create_default_files(const char *template_path, * values we might have just re-read from the config. */ if (init_shared_repository != -1) - set_shared_repository(init_shared_repository); + repo_settings_set_shared_repository(the_repository, + init_shared_repository); is_bare_repository_cfg = !work_tree; @@ -2351,21 +2351,21 @@ static int create_default_files(const char *template_path, * We would have created the above under user's umask -- under * shared-repository settings, we would need to fix them up. */ - if (get_shared_repository()) { - adjust_shared_perm(repo_get_git_dir(the_repository)); + if (repo_settings_get_shared_repository(the_repository)) { + adjust_shared_perm(the_repository, repo_get_git_dir(the_repository)); } initialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, reinit); /* Check filemode trustability */ - path = git_path_buf(&buf, "config"); + repo_git_path_replace(the_repository, &path, "config"); filemode = TEST_FILEMODE; - if (TEST_FILEMODE && !lstat(path, &st1)) { + if (TEST_FILEMODE && !lstat(path.buf, &st1)) { struct stat st2; - filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) && - !lstat(path, &st2) && + filemode = (!chmod(path.buf, st1.st_mode ^ S_IXUSR) && + !lstat(path.buf, &st2) && st1.st_mode != st2.st_mode && - !chmod(path, st1.st_mode)); + !chmod(path.buf, st1.st_mode)); if (filemode && !reinit && (st1.st_mode & S_IXUSR)) filemode = 0; } @@ -2384,24 +2384,24 @@ static int create_default_files(const char *template_path, if (!reinit) { /* Check if symlink is supported in the work tree */ - path = git_path_buf(&buf, "tXXXXXX"); - if (!close(xmkstemp(path)) && - !unlink(path) && - !symlink("testing", path) && - !lstat(path, &st1) && + repo_git_path_replace(the_repository, &path, "tXXXXXX"); + if (!close(xmkstemp(path.buf)) && + !unlink(path.buf) && + !symlink("testing", path.buf) && + !lstat(path.buf, &st1) && S_ISLNK(st1.st_mode)) - unlink(path); /* good */ + unlink(path.buf); /* good */ else git_config_set("core.symlinks", "false"); /* Check if the filesystem is case-insensitive */ - path = git_path_buf(&buf, "CoNfIg"); - if (!access(path, F_OK)) + repo_git_path_replace(the_repository, &path, "CoNfIg"); + if (!access(path.buf, F_OK)) git_config_set("core.ignorecase", "true"); probe_utf8_pathname_composition(); } - strbuf_release(&buf); + strbuf_release(&path); return reinit; } @@ -2413,15 +2413,15 @@ static void create_object_directory(void) strbuf_addstr(&path, repo_get_object_directory(the_repository)); baselen = path.len; - safe_create_dir(path.buf, 1); + safe_create_dir(the_repository, path.buf, 1); strbuf_setlen(&path, baselen); strbuf_addstr(&path, "/pack"); - safe_create_dir(path.buf, 1); + safe_create_dir(the_repository, path.buf, 1); strbuf_setlen(&path, baselen); strbuf_addstr(&path, "/info"); - safe_create_dir(path.buf, 1); + safe_create_dir(the_repository, path.buf, 1); strbuf_release(&path); } @@ -2517,7 +2517,9 @@ static void repository_format_configure(struct repository_format *repo_fmt, int env_algo = hash_algo_by_name(env); if (env_algo == GIT_HASH_UNKNOWN) die(_("unknown hash algorithm '%s'"), env); - repo_fmt->hash_algo = env_algo; + if (repo_fmt->version < 0 || + repo_fmt->hash_algo == GIT_HASH_UNKNOWN) + repo_fmt->hash_algo = env_algo; } else if (cfg.hash != GIT_HASH_UNKNOWN) { repo_fmt->hash_algo = cfg.hash; } @@ -2534,7 +2536,9 @@ static void repository_format_configure(struct repository_format *repo_fmt, ref_format = ref_storage_format_by_name(env); if (ref_format == REF_STORAGE_FORMAT_UNKNOWN) die(_("unknown ref storage format '%s'"), env); - repo_fmt->ref_storage_format = ref_format; + if (repo_fmt->version < 0 || + repo_fmt->ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) + repo_fmt->ref_storage_format = ref_format; } else if (cfg.ref_format != REF_STORAGE_FORMAT_UNKNOWN) { repo_fmt->ref_storage_format = cfg.ref_format; } @@ -2588,7 +2592,7 @@ int init_db(const char *git_dir, const char *real_git_dir, */ git_config(platform_core_config, NULL); - safe_create_dir(git_dir, 0); + safe_create_dir(the_repository, git_dir, 0); reinit = create_default_files(template_dir, original_git_dir, &repo_fmt, init_shared_repository); @@ -2598,7 +2602,7 @@ int init_db(const char *git_dir, const char *real_git_dir, initial_branch, flags & INIT_DB_QUIET); create_object_directory(); - if (get_shared_repository()) { + if (repo_settings_get_shared_repository(the_repository)) { char buf[10]; /* We do not spell "group" and such, so that * the configuration can be read by older version @@ -2606,12 +2610,12 @@ int init_db(const char *git_dir, const char *real_git_dir, * and compatibility values for PERM_GROUP and * PERM_EVERYBODY. */ - if (get_shared_repository() < 0) + if (repo_settings_get_shared_repository(the_repository) < 0) /* force to the mode value */ - xsnprintf(buf, sizeof(buf), "0%o", -get_shared_repository()); - else if (get_shared_repository() == PERM_GROUP) + xsnprintf(buf, sizeof(buf), "0%o", -repo_settings_get_shared_repository(the_repository)); + else if (repo_settings_get_shared_repository(the_repository) == PERM_GROUP) xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP); - else if (get_shared_repository() == PERM_EVERYBODY) + else if (repo_settings_get_shared_repository(the_repository) == PERM_EVERYBODY) xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY); else BUG("invalid value for shared_repository"); @@ -2623,12 +2627,12 @@ int init_db(const char *git_dir, const char *real_git_dir, int len = strlen(git_dir); if (reinit) - printf(get_shared_repository() + printf(repo_settings_get_shared_repository(the_repository) ? _("Reinitialized existing shared Git repository in %s%s\n") : _("Reinitialized existing Git repository in %s%s\n"), git_dir, len && git_dir[len-1] != '/' ? "/" : ""); else - printf(get_shared_repository() + printf(repo_settings_get_shared_repository(the_repository) ? _("Initialized empty shared Git repository in %s%s\n") : _("Initialized empty Git repository in %s%s\n"), git_dir, len && git_dir[len-1] != '/' ? "/" : ""); @@ -1,5 +1,4 @@ #define USE_THE_REPOSITORY_VARIABLE -#define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" #include "hex.h" @@ -134,7 +133,8 @@ static void free_depth_in_slab(int **ptr) struct commit_list *get_shallow_commits(struct object_array *heads, int depth, int shallow_flag, int not_shallow_flag) { - int i = 0, cur_depth = 0; + size_t i = 0; + int cur_depth = 0; struct commit_list *result = NULL; struct object_array stack = OBJECT_ARRAY_INIT; struct commit *commit = NULL; @@ -335,16 +335,16 @@ static int write_shallow_commits_1(struct strbuf *out, int use_pack_protocol, const struct oid_array *extra, unsigned flags) { - struct write_shallow_data data; - int i; - data.out = out; - data.use_pack_protocol = use_pack_protocol; - data.count = 0; - data.flags = flags; + struct write_shallow_data data = { + .out = out, + .use_pack_protocol = use_pack_protocol, + .flags = flags, + }; + for_each_commit_graft(write_one_shallow, &data); if (!extra) return data.count; - for (i = 0; i < extra->nr; i++) { + for (size_t i = 0; i < extra->nr; i++) { strbuf_addstr(out, oid_to_hex(extra->oid + i)); strbuf_addch(out, '\n'); data.count++; @@ -364,7 +364,9 @@ const char *setup_temporary_shallow(const struct oid_array *extra) struct strbuf sb = STRBUF_INIT; if (write_shallow_commits(&sb, 0, extra)) { - temp = xmks_tempfile(git_path("shallow_XXXXXX")); + char *path = repo_git_path(the_repository, "shallow_XXXXXX"); + temp = xmks_tempfile(path); + free(path); if (write_in_full(temp->fd, sb.buf, sb.len) < 0 || close_tempfile_gently(temp) < 0) @@ -466,7 +468,6 @@ struct trace_key trace_shallow = TRACE_KEY_INIT(SHALLOW); */ void prepare_shallow_info(struct shallow_info *info, struct oid_array *sa) { - int i; trace_printf_key(&trace_shallow, "shallow: prepare_shallow_info\n"); memset(info, 0, sizeof(*info)); info->shallow = sa; @@ -474,7 +475,7 @@ void prepare_shallow_info(struct shallow_info *info, struct oid_array *sa) return; ALLOC_ARRAY(info->ours, sa->nr); ALLOC_ARRAY(info->theirs, sa->nr); - for (i = 0; i < sa->nr; i++) { + for (size_t i = 0; i < sa->nr; i++) { if (repo_has_object_file(the_repository, sa->oid + i)) { struct commit_graft *graft; graft = lookup_commit_graft(the_repository, @@ -507,7 +508,7 @@ void clear_shallow_info(struct shallow_info *info) void remove_nonexistent_theirs_shallow(struct shallow_info *info) { struct object_id *oid = info->shallow->oid; - int i, dst; + size_t i, dst; trace_printf_key(&trace_shallow, "shallow: remove_nonexistent_theirs_shallow\n"); for (i = dst = 0; i < info->nr_theirs; i++) { if (i != dst) @@ -535,7 +536,7 @@ static uint32_t *paint_alloc(struct paint_info *info) unsigned nr = DIV_ROUND_UP(info->nr_bits, 32); unsigned size = nr * sizeof(uint32_t); void *p; - if (!info->pool_count || size > info->end - info->free) { + if (!info->pool_count || info->end < info->free + size) { if (size > POOL_SIZE) BUG("pool size too small for %d in paint_alloc()", size); @@ -560,7 +561,7 @@ static void paint_down(struct paint_info *info, const struct object_id *oid, { unsigned int i, nr; struct commit_list *head = NULL; - int bitmap_nr = DIV_ROUND_UP(info->nr_bits, 32); + size_t bitmap_nr = DIV_ROUND_UP(info->nr_bits, 32); size_t bitmap_size = st_mult(sizeof(uint32_t), bitmap_nr); struct commit *c = lookup_commit_reference_gently(the_repository, oid, 1); @@ -660,7 +661,7 @@ void assign_shallow_commits_to_refs(struct shallow_info *info, struct object_id *oid = info->shallow->oid; struct oid_array *ref = info->ref; unsigned int i, nr; - int *shallow, nr_shallow = 0; + size_t *shallow, nr_shallow = 0; struct paint_info pi; trace_printf_key(&trace_shallow, "shallow: assign_shallow_commits_to_refs\n"); @@ -735,7 +736,7 @@ void assign_shallow_commits_to_refs(struct shallow_info *info, struct commit_array { struct commit **commits; - int nr, alloc; + size_t nr, alloc; }; static int add_ref(const char *refname UNUSED, @@ -753,12 +754,11 @@ static int add_ref(const char *refname UNUSED, return 0; } -static void update_refstatus(int *ref_status, int nr, uint32_t *bitmap) +static void update_refstatus(int *ref_status, size_t nr, uint32_t *bitmap) { - unsigned int i; if (!ref_status) return; - for (i = 0; i < nr; i++) + for (size_t i = 0; i < nr; i++) if (bitmap[i / 32] & (1U << (i % 32))) ref_status[i]++; } @@ -773,8 +773,8 @@ static void post_assign_shallow(struct shallow_info *info, struct object_id *oid = info->shallow->oid; struct commit *c; uint32_t **bitmap; - int dst, i, j; - int bitmap_nr = DIV_ROUND_UP(info->ref->nr, 32); + size_t dst, i, j; + size_t bitmap_nr = DIV_ROUND_UP(info->ref->nr, 32); struct commit_array ca; trace_printf_key(&trace_shallow, "shallow: post_assign_shallow\n"); @@ -59,8 +59,8 @@ void prune_shallow(unsigned options); */ struct shallow_info { struct oid_array *shallow; - int *ours, nr_ours; - int *theirs, nr_theirs; + size_t *ours, nr_ours; + size_t *theirs, nr_theirs; struct oid_array *ref; /* for receive-pack */ @@ -69,7 +69,7 @@ struct shallow_info { int *reachable; int *shallow_ref; struct commit **commits; - int nr_commits; + size_t nr_commits; }; void prepare_shallow_info(struct shallow_info *, struct oid_array *); diff --git a/simple-ipc.h b/simple-ipc.h index 3916eaf70d..701e005cb8 100644 --- a/simple-ipc.h +++ b/simple-ipc.h @@ -2,7 +2,7 @@ #define GIT_SIMPLE_IPC_H /* - * See Documentation/technical/api-simple-ipc.txt + * See Documentation/technical/api-simple-ipc.adoc */ enum ipc_active_state { diff --git a/submodule.c b/submodule.c index b361076c5b..0530e8cf24 100644 --- a/submodule.c +++ b/submodule.c @@ -536,7 +536,8 @@ static struct repository *open_submodule(const char *path) struct strbuf sb = STRBUF_INIT; struct repository *out = xmalloc(sizeof(*out)); - if (submodule_to_gitdir(&sb, path) || repo_init(out, sb.buf, NULL)) { + if (submodule_to_gitdir(the_repository, &sb, path) || + repo_init(out, sb.buf, NULL)) { strbuf_release(&sb); free(out); return NULL; @@ -1315,7 +1316,7 @@ static int repo_has_absorbed_submodules(struct repository *r) int ret; struct strbuf buf = STRBUF_INIT; - strbuf_repo_git_path(&buf, r, "modules/"); + repo_git_path_append(r, &buf, "modules/"); ret = file_exists(buf.buf) && !is_empty_dir(buf.buf); strbuf_release(&buf); return ret; @@ -2572,7 +2573,8 @@ int get_superproject_working_tree(struct strbuf *buf) * Put the gitdir for a submodule (given relative to the main * repository worktree) into `buf`, or return -1 on error. */ -int submodule_to_gitdir(struct strbuf *buf, const char *submodule) +int submodule_to_gitdir(struct repository *repo, + struct strbuf *buf, const char *submodule) { const struct submodule *sub; const char *git_dir; @@ -2592,14 +2594,13 @@ int submodule_to_gitdir(struct strbuf *buf, const char *submodule) strbuf_addstr(buf, git_dir); } if (!is_git_directory(buf->buf)) { - sub = submodule_from_path(the_repository, null_oid(), - submodule); + sub = submodule_from_path(repo, null_oid(), submodule); if (!sub) { ret = -1; goto cleanup; } strbuf_reset(buf); - submodule_name_to_gitdir(buf, the_repository, sub->name); + submodule_name_to_gitdir(buf, repo, sub->name); } cleanup: @@ -2629,6 +2630,6 @@ void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r, * administrators can explicitly set. Nothing has been decided, * so for now, just append the name at the end of the path. */ - strbuf_repo_git_path(buf, r, "modules/"); + repo_git_path_append(r, buf, "modules/"); strbuf_addstr(buf, submodule_name); } diff --git a/submodule.h b/submodule.h index 4deb1b5f84..db980c1d08 100644 --- a/submodule.h +++ b/submodule.h @@ -136,7 +136,8 @@ int push_unpushed_submodules(struct repository *r, * path of that submodule in 'buf'. Return -1 on error or when the * submodule is not initialized. */ -int submodule_to_gitdir(struct strbuf *buf, const char *submodule); +int submodule_to_gitdir(struct repository *repo, + struct strbuf *buf, const char *submodule); /* * Given a submodule name, create a path to where the submodule's gitdir lives diff --git a/t/Makefile b/t/Makefile index daa5fcae86..2994eb5fa9 100644 --- a/t/Makefile +++ b/t/Makefile @@ -177,3 +177,18 @@ perf: .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \ check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS) + +.PHONY: libgit-sys-test libgit-rs-test +libgit-sys-test: + $(QUIET)(\ + cd ../contrib/libgit-sys && \ + cargo test \ + ) +libgit-rs-test: + $(QUIET)(\ + cd ../contrib/libgit-rs && \ + cargo test \ + ) +ifdef INCLUDE_LIBGIT_RS +all:: libgit-sys-test libgit-rs-test +endif @@ -471,6 +471,10 @@ a test and then fails then the whole test run will abort. This can help to make sure the expected tests are executed and not silently skipped when their dependency breaks or is simply not present in a new environment. +GIT_TEST_NAME_HASH_VERSION=<int>, when set, causes 'git pack-objects' to +assume '--name-hash-version=<n>'. + + Naming Tests ------------ diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh index 6e3bcc4aec..6cb0ff11de 100755 --- a/t/aggregate-results.sh +++ b/t/aggregate-results.sh @@ -44,7 +44,7 @@ then tr -s "," "\n" | grep -v '^$' | sort -u | - paste -s -d ' ') + paste -s -d ' ' -) if test -n "$unique_missing_prereq" then printf "\nmissing prereq: $unique_missing_prereq\n\n" diff --git a/t/helper/meson.build b/t/helper/meson.build index 5e83884246..d2cabaa2bc 100644 --- a/t/helper/meson.build +++ b/t/helper/meson.build @@ -34,12 +34,14 @@ test_tool_sources = [ 'test-match-trees.c', 'test-mergesort.c', 'test-mktemp.c', + 'test-name-hash.c', 'test-online-cpus.c', 'test-pack-mtimes.c', 'test-parse-options.c', 'test-parse-pathspec-file.c', 'test-partial-clone.c', 'test-path-utils.c', + 'test-path-walk.c', 'test-pcre2-config.c', 'test-pkt-line.c', 'test-proc-receive.c', @@ -78,14 +80,14 @@ test_tool_sources = [ test_tool = executable('test-tool', sources: test_tool_sources, - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], ) bin_wrappers += test_tool test_dependencies += test_tool test_fake_ssh = executable('test-fake-ssh', sources: 'test-fake-ssh.c', - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], ) bin_wrappers += test_fake_ssh test_dependencies += test_fake_ssh diff --git a/t/helper/test-csprng.c b/t/helper/test-csprng.c index a4a0aca617..c86dcc4870 100644 --- a/t/helper/test-csprng.c +++ b/t/helper/test-csprng.c @@ -15,7 +15,7 @@ int cmd__csprng(int argc, const char **argv) while (count) { unsigned long chunk = count < sizeof(buf) ? count : sizeof(buf); - if (csprng_bytes(buf, chunk) < 0) { + if (csprng_bytes(buf, chunk, 0) < 0) { perror("failed to read"); return 5; } diff --git a/t/helper/test-dir-iterator.c b/t/helper/test-dir-iterator.c index 6b297bd753..8d46e8ba40 100644 --- a/t/helper/test-dir-iterator.c +++ b/t/helper/test-dir-iterator.c @@ -53,6 +53,7 @@ int cmd__dir_iterator(int argc, const char **argv) printf("(%s) [%s] %s\n", diter->relative_path, diter->basename, diter->path.buf); } + dir_iterator_free(diter); if (iter_status != ITER_DONE) { printf("dir_iterator_advance failure\n"); diff --git a/t/helper/test-hash-speed.c b/t/helper/test-hash-speed.c index 80df1aae66..fbf67fe6bd 100644 --- a/t/helper/test-hash-speed.c +++ b/t/helper/test-hash-speed.c @@ -3,16 +3,16 @@ #define NUM_SECONDS 3 -static inline void compute_hash(const struct git_hash_algo *algo, git_hash_ctx *ctx, uint8_t *final, const void *p, size_t len) +static inline void compute_hash(const struct git_hash_algo *algo, struct git_hash_ctx *ctx, uint8_t *final, const void *p, size_t len) { algo->init_fn(ctx); - algo->update_fn(ctx, p, len); - algo->final_fn(final, ctx); + git_hash_update(ctx, p, len); + git_hash_final(final, ctx); } int cmd__hash_speed(int ac, const char **av) { - git_hash_ctx ctx; + struct git_hash_ctx ctx; unsigned char hash[GIT_MAX_RAWSZ]; clock_t initial, start, end; unsigned bufsizes[] = { 64, 256, 1024, 8192, 16384 }; diff --git a/t/helper/test-hash.c b/t/helper/test-hash.c index 45d829c908..f0ee61c8b4 100644 --- a/t/helper/test-hash.c +++ b/t/helper/test-hash.c @@ -1,14 +1,16 @@ #include "test-tool.h" #include "hex.h" -int cmd_hash_impl(int ac, const char **av, int algo) +int cmd_hash_impl(int ac, const char **av, int algo, int unsafe) { - git_hash_ctx ctx; + struct git_hash_ctx ctx; unsigned char hash[GIT_MAX_HEXSZ]; unsigned bufsz = 8192; int binary = 0; char *buffer; const struct git_hash_algo *algop = &hash_algos[algo]; + if (unsafe) + algop = unsafe_hash_algo(algop); if (ac == 2) { if (!strcmp(av[1], "-b")) @@ -46,9 +48,9 @@ int cmd_hash_impl(int ac, const char **av, int algo) } if (this_sz == 0) break; - algop->update_fn(&ctx, buffer, this_sz); + git_hash_update(&ctx, buffer, this_sz); } - algop->final_fn(hash, &ctx); + git_hash_final(hash, &ctx); if (binary) fwrite(hash, 1, algop->rawsz, stdout); diff --git a/t/helper/test-name-hash.c b/t/helper/test-name-hash.c new file mode 100644 index 0000000000..af1d52de10 --- /dev/null +++ b/t/helper/test-name-hash.c @@ -0,0 +1,23 @@ +/* + * test-name-hash.c: Read a list of paths over stdin and report on their + * name-hash and full name-hash. + */ + +#include "test-tool.h" +#include "git-compat-util.h" +#include "pack-objects.h" +#include "strbuf.h" + +int cmd__name_hash(int argc UNUSED, const char **argv UNUSED) +{ + struct strbuf line = STRBUF_INIT; + + while (!strbuf_getline(&line, stdin)) { + printf("%10u ", pack_name_hash(line.buf)); + printf("%10u ", pack_name_hash_v2((unsigned const char *)line.buf)); + printf("%s\n", line.buf); + } + + strbuf_release(&line); + return 0; +} diff --git a/t/helper/test-path-walk.c b/t/helper/test-path-walk.c new file mode 100644 index 0000000000..61e845e5ec --- /dev/null +++ b/t/helper/test-path-walk.c @@ -0,0 +1,132 @@ +#define USE_THE_REPOSITORY_VARIABLE + +#include "test-tool.h" +#include "dir.h" +#include "environment.h" +#include "hex.h" +#include "object-name.h" +#include "object.h" +#include "pretty.h" +#include "revision.h" +#include "setup.h" +#include "parse-options.h" +#include "strbuf.h" +#include "path-walk.h" +#include "oid-array.h" + +static const char * const path_walk_usage[] = { + N_("test-tool path-walk <options> -- <revision-options>"), + NULL +}; + +struct path_walk_test_data { + uintmax_t batch_nr; + + uintmax_t commit_nr; + uintmax_t tree_nr; + uintmax_t blob_nr; + uintmax_t tag_nr; +}; + +static int emit_block(const char *path, struct oid_array *oids, + enum object_type type, void *data) +{ + struct path_walk_test_data *tdata = data; + const char *typestr; + + if (type == OBJ_TREE) + tdata->tree_nr += oids->nr; + else if (type == OBJ_BLOB) + tdata->blob_nr += oids->nr; + else if (type == OBJ_COMMIT) + tdata->commit_nr += oids->nr; + else if (type == OBJ_TAG) + tdata->tag_nr += oids->nr; + else + BUG("we do not understand this type"); + + typestr = type_name(type); + + /* This should never be output during tests. */ + if (!oids->nr) + printf("%"PRIuMAX":%s:%s:EMPTY\n", + tdata->batch_nr, typestr, path); + + for (size_t i = 0; i < oids->nr; i++) { + struct object *o = lookup_unknown_object(the_repository, + &oids->oid[i]); + printf("%"PRIuMAX":%s:%s:%s%s\n", + tdata->batch_nr, typestr, path, + oid_to_hex(&oids->oid[i]), + o->flags & UNINTERESTING ? ":UNINTERESTING" : ""); + } + + tdata->batch_nr++; + return 0; +} + +int cmd__path_walk(int argc, const char **argv) +{ + int res, stdin_pl = 0; + struct rev_info revs = REV_INFO_INIT; + struct path_walk_info info = PATH_WALK_INFO_INIT; + struct path_walk_test_data data = { 0 }; + struct option options[] = { + OPT_BOOL(0, "blobs", &info.blobs, + N_("toggle inclusion of blob objects")), + OPT_BOOL(0, "commits", &info.commits, + N_("toggle inclusion of commit objects")), + OPT_BOOL(0, "tags", &info.tags, + N_("toggle inclusion of tag objects")), + OPT_BOOL(0, "trees", &info.trees, + N_("toggle inclusion of tree objects")), + OPT_BOOL(0, "prune", &info.prune_all_uninteresting, + N_("toggle pruning of uninteresting paths")), + OPT_BOOL(0, "stdin-pl", &stdin_pl, + N_("read a pattern list over stdin")), + OPT_END(), + }; + + setup_git_directory(); + revs.repo = the_repository; + + argc = parse_options(argc, argv, NULL, + options, path_walk_usage, + PARSE_OPT_KEEP_UNKNOWN_OPT | PARSE_OPT_KEEP_ARGV0); + + if (argc > 1) + setup_revisions(argc, argv, &revs, NULL); + else + usage(path_walk_usage[0]); + + info.revs = &revs; + info.path_fn = emit_block; + info.path_fn_data = &data; + + if (stdin_pl) { + struct strbuf in = STRBUF_INIT; + CALLOC_ARRAY(info.pl, 1); + + info.pl->use_cone_patterns = 1; + + strbuf_fread(&in, 2048, stdin); + add_patterns_from_buffer(in.buf, in.len, "", 0, info.pl); + strbuf_release(&in); + } + + res = walk_objects_by_path(&info); + + printf("commits:%" PRIuMAX "\n" + "trees:%" PRIuMAX "\n" + "blobs:%" PRIuMAX "\n" + "tags:%" PRIuMAX "\n", + data.commit_nr, data.tree_nr, data.blob_nr, data.tag_nr); + + if (info.pl) { + clear_pattern_list(info.pl); + free(info.pl); + } + + release_revisions(&revs); + return res; +} diff --git a/t/helper/test-progress.c b/t/helper/test-progress.c index 44be2645e9..1f75b7bd19 100644 --- a/t/helper/test-progress.c +++ b/t/helper/test-progress.c @@ -17,10 +17,14 @@ * * See 't0500-progress-display.sh' for examples. */ + +#define USE_THE_REPOSITORY_VARIABLE #define GIT_TEST_PROGRESS_ONLY + #include "test-tool.h" #include "parse-options.h" #include "progress.h" +#include "repository.h" #include "strbuf.h" #include "string-list.h" @@ -64,7 +68,7 @@ int cmd__progress(int argc, const char **argv) else die("invalid input: '%s'", line.buf); - progress = start_progress(title, total); + progress = start_progress(the_repository, title, total); } else if (skip_prefix(line.buf, "progress ", (const char **) &end)) { uint64_t item_count = strtoull(end, &end, 10); if (*end != '\0') diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c index 01cf77ae65..028ec00306 100644 --- a/t/helper/test-reach.c +++ b/t/helper/test-reach.c @@ -35,7 +35,7 @@ int cmd__reach(int ac, const char **av) struct commit_list *X, *Y; struct object_array X_obj = OBJECT_ARRAY_INIT; struct commit **X_array, **Y_array; - int X_nr, X_alloc, Y_nr, Y_alloc; + size_t X_nr, X_alloc, Y_nr, Y_alloc; struct strbuf buf = STRBUF_INIT; struct repository *r = the_repository; @@ -157,7 +157,7 @@ int cmd__reach(int ac, const char **av) clear_contains_cache(&cache); } else if (!strcmp(av[1], "get_reachable_subset")) { const int reachable_flag = 1; - int i, count = 0; + int count = 0; struct commit_list *current; struct commit_list *list = get_reachable_subset(X_array, X_nr, Y_array, Y_nr, @@ -169,7 +169,7 @@ int cmd__reach(int ac, const char **av) oid_to_hex(&list->item->object.oid)); count++; } - for (i = 0; i < Y_nr; i++) { + for (size_t i = 0; i < Y_nr; i++) { if (Y_array[i]->object.flags & reachable_flag) count--; } diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 1cc05f043a..e00fce592b 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -75,11 +75,10 @@ static const char **get_store(const char **argv, struct ref_store **refs) *refs = get_main_ref_store(the_repository); } else if (skip_prefix(argv[0], "submodule:", &gitdir)) { struct strbuf sb = STRBUF_INIT; - int ret; - ret = strbuf_git_path_submodule(&sb, gitdir, "objects/"); - if (ret) - die("strbuf_git_path_submodule failed: %d", ret); + if (!repo_submodule_path_append(the_repository, + &sb, gitdir, "objects/")) + die("computing submodule path failed"); add_to_alternates_memory(sb.buf); strbuf_release(&sb); diff --git a/t/helper/test-rot13-filter.c b/t/helper/test-rot13-filter.c index ff407b575c..722b1cbe77 100644 --- a/t/helper/test-rot13-filter.c +++ b/t/helper/test-rot13-filter.c @@ -1,6 +1,6 @@ /* * Example implementation for the Git filter protocol version 2 - * See Documentation/gitattributes.txt, section "Filter Protocol" + * See Documentation/gitattributes.adoc, section "Filter Protocol" * * Usage: test-tool rot13-filter [--always-delay] --log=<path> <capabilities> * diff --git a/t/helper/test-serve-v2.c b/t/helper/test-serve-v2.c index 054cbcf5d8..63a200b8d4 100644 --- a/t/helper/test-serve-v2.c +++ b/t/helper/test-serve-v2.c @@ -1,6 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "test-tool.h" #include "gettext.h" #include "parse-options.h" +#include "repository.h" #include "serve.h" #include "setup.h" @@ -28,9 +31,9 @@ int cmd__serve_v2(int argc, const char **argv) PARSE_OPT_KEEP_UNKNOWN_OPT); if (advertise_capabilities) - protocol_v2_advertise_capabilities(); + protocol_v2_advertise_capabilities(the_repository); else - protocol_v2_serve_loop(stateless_rpc); + protocol_v2_serve_loop(the_repository, stateless_rpc); return 0; } diff --git a/t/helper/test-sha1.c b/t/helper/test-sha1.c index e60d000c03..349540c4df 100644 --- a/t/helper/test-sha1.c +++ b/t/helper/test-sha1.c @@ -3,7 +3,7 @@ int cmd__sha1(int ac, const char **av) { - return cmd_hash_impl(ac, av, GIT_HASH_SHA1); + return cmd_hash_impl(ac, av, GIT_HASH_SHA1, 0); } int cmd__sha1_is_sha1dc(int argc UNUSED, const char **argv UNUSED) @@ -13,3 +13,8 @@ int cmd__sha1_is_sha1dc(int argc UNUSED, const char **argv UNUSED) #endif return 1; } + +int cmd__sha1_unsafe(int ac, const char **av) +{ + return cmd_hash_impl(ac, av, GIT_HASH_SHA1, 1); +} diff --git a/t/helper/test-sha1.sh b/t/helper/test-sha1.sh index 84594885c7..bf387d3db1 100755 --- a/t/helper/test-sha1.sh +++ b/t/helper/test-sha1.sh @@ -3,25 +3,31 @@ dd if=/dev/zero bs=1048576 count=100 2>/dev/null | /usr/bin/time t/helper/test-tool sha1 >/dev/null +dd if=/dev/zero bs=1048576 count=100 2>/dev/null | +/usr/bin/time t/helper/test-tool sha1-unsafe >/dev/null + while read expect cnt pfx do case "$expect" in '#'*) continue ;; esac - actual=$( - { - test -z "$pfx" || echo "$pfx" - dd if=/dev/zero bs=1048576 count=$cnt 2>/dev/null | - perl -pe 'y/\000/g/' - } | ./t/helper/test-tool sha1 $cnt - ) - if test "$expect" = "$actual" - then - echo "OK: $expect $cnt $pfx" - else - echo >&2 "OOPS: $cnt" - echo >&2 "expect: $expect" - echo >&2 "actual: $actual" - exit 1 - fi + for sha1 in sha1 sha1-unsafe + do + actual=$( + { + test -z "$pfx" || echo "$pfx" + dd if=/dev/zero bs=1048576 count=$cnt 2>/dev/null | + perl -pe 'y/\000/g/' + } | ./t/helper/test-tool $sha1 $cnt + ) + if test "$expect" = "$actual" + then + echo "OK ($sha1): $expect $cnt $pfx" + else + echo >&2 "OOPS ($sha1): $cnt" + echo >&2 "expect ($sha1): $expect" + echo >&2 "actual ($sha1): $actual" + exit 1 + fi + done done <<EOF da39a3ee5e6b4b0d3255bfef95601890afd80709 0 3f786850e387550fdab836ed7e6dc881de23001b 0 a diff --git a/t/helper/test-sha256.c b/t/helper/test-sha256.c index 2fb20438f3..7fd0aa1fcd 100644 --- a/t/helper/test-sha256.c +++ b/t/helper/test-sha256.c @@ -3,5 +3,5 @@ int cmd__sha256(int ac, const char **av) { - return cmd_hash_impl(ac, av, GIT_HASH_SHA256); + return cmd_hash_impl(ac, av, GIT_HASH_SHA256, 0); } diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c index fb5927775d..03cc5eea2c 100644 --- a/t/helper/test-simple-ipc.c +++ b/t/helper/test-simple-ipc.c @@ -612,8 +612,8 @@ int cmd__simple_ipc(int argc, const char **argv) if (argc < 2) usage_with_options(simple_ipc_usage, options); - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(simple_ipc_usage, options); + show_usage_with_options_if_asked(argc, argv, + simple_ipc_usage, options); if (argc == 2 && !strcmp(argv[1], "SUPPORTS_SIMPLE_IPC")) return 0; diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index 4a7aa993ba..50dc4dac4e 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -44,6 +44,7 @@ static struct test_cmd cmds[] = { { "match-trees", cmd__match_trees }, { "mergesort", cmd__mergesort }, { "mktemp", cmd__mktemp }, + { "name-hash", cmd__name_hash }, { "online-cpus", cmd__online_cpus }, { "pack-mtimes", cmd__pack_mtimes }, { "parse-options", cmd__parse_options }, @@ -52,6 +53,7 @@ static struct test_cmd cmds[] = { { "parse-subcommand", cmd__parse_subcommand }, { "partial-clone", cmd__partial_clone }, { "path-utils", cmd__path_utils }, + { "path-walk", cmd__path_walk }, { "pcre2-config", cmd__pcre2_config }, { "pkt-line", cmd__pkt_line }, { "proc-receive", cmd__proc_receive }, @@ -70,6 +72,7 @@ static struct test_cmd cmds[] = { { "serve-v2", cmd__serve_v2 }, { "sha1", cmd__sha1 }, { "sha1-is-sha1dc", cmd__sha1_is_sha1dc }, + { "sha1-unsafe", cmd__sha1_unsafe }, { "sha256", cmd__sha256 }, { "sigchain", cmd__sigchain }, { "simple-ipc", cmd__simple_ipc }, diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index 21802ac27d..6d62a5b53d 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -37,6 +37,7 @@ int cmd__lazy_init_name_hash(int argc, const char **argv); int cmd__match_trees(int argc, const char **argv); int cmd__mergesort(int argc, const char **argv); int cmd__mktemp(int argc, const char **argv); +int cmd__name_hash(int argc, const char **argv); int cmd__online_cpus(int argc, const char **argv); int cmd__pack_mtimes(int argc, const char **argv); int cmd__parse_options(int argc, const char **argv); @@ -45,6 +46,7 @@ int cmd__parse_pathspec_file(int argc, const char** argv); int cmd__parse_subcommand(int argc, const char **argv); int cmd__partial_clone(int argc, const char **argv); int cmd__path_utils(int argc, const char **argv); +int cmd__path_walk(int argc, const char **argv); int cmd__pcre2_config(int argc, const char **argv); int cmd__pkt_line(int argc, const char **argv); int cmd__proc_receive(int argc, const char **argv); @@ -63,6 +65,7 @@ int cmd__scrap_cache_tree(int argc, const char **argv); int cmd__serve_v2(int argc, const char **argv); int cmd__sha1(int argc, const char **argv); int cmd__sha1_is_sha1dc(int argc, const char **argv); +int cmd__sha1_unsafe(int argc, const char **argv); int cmd__sha256(int argc, const char **argv); int cmd__sigchain(int argc, const char **argv); int cmd__simple_ipc(int argc, const char **argv); @@ -81,6 +84,6 @@ int cmd__windows_named_pipe(int argc, const char **argv); #endif int cmd__write_cache(int argc, const char **argv); -int cmd_hash_impl(int ac, const char **av, int algo); +int cmd_hash_impl(int ac, const char **av, int algo, int unsafe); #endif diff --git a/t/interop/Makefile b/t/interop/Makefile index 6911c2915a..4ff4ed0616 100644 --- a/t/interop/Makefile +++ b/t/interop/Makefile @@ -1,3 +1,6 @@ +# The default target of this Makefile is... +all:: + # Import tree-wide shared Makefile behavior and libraries include ../../shared.mak @@ -8,7 +11,7 @@ SHELL_PATH ?= $(SHELL) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) T = $(sort $(wildcard i[0-9][0-9][0-9][0-9]-*.sh)) -all: $(T) +all:: $(T) $(T): @echo "*** $@ ***"; '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) diff --git a/t/lib-credential.sh b/t/lib-credential.sh index 58b9c74060..cc6bf9aa5f 100644 --- a/t/lib-credential.sh +++ b/t/lib-credential.sh @@ -566,6 +566,21 @@ helper_test_authtype() { EOF ' + test_expect_success "helper ($HELPER) gets authtype and credential only if request has authtype capability" ' + check fill $HELPER <<-\EOF + protocol=https + host=git.example.com + -- + protocol=https + host=git.example.com + username=askpass-username + password=askpass-password + -- + askpass: Username for '\''https://git.example.com'\'': + askpass: Password for '\''https://askpass-username@git.example.com'\'': + EOF + ' + test_expect_success "helper ($HELPER) stores authtype and credential with username" ' check approve $HELPER <<-\EOF capability[]=authtype diff --git a/t/lib-gettext.sh b/t/lib-gettext.sh index 7a734c6973..b3dd68b0b9 100644 --- a/t/lib-gettext.sh +++ b/t/lib-gettext.sh @@ -7,7 +7,7 @@ . ./test-lib.sh GIT_TEXTDOMAINDIR="$GIT_TEST_TEXTDOMAINDIR" -GIT_PO_PATH="$GIT_TEST_POPATH" +GIT_PO_PATH="$GIT_SOURCE_DIR/po" export GIT_TEXTDOMAINDIR GIT_PO_PATH if test -n "$GIT_TEST_INSTALLED" diff --git a/t/meson.build b/t/meson.build index 602ebfe6a2..8b3aed14ea 100644 --- a/t/meson.build +++ b/t/meson.build @@ -1,11 +1,23 @@ clar_test_suites = [ 'unit-tests/u-ctype.c', + 'unit-tests/u-example-decorate.c', + 'unit-tests/u-hash.c', + 'unit-tests/u-hashmap.c', + 'unit-tests/u-mem-pool.c', + 'unit-tests/u-oid-array.c', + 'unit-tests/u-oidmap.c', + 'unit-tests/u-oidtree.c', + 'unit-tests/u-prio-queue.c', + 'unit-tests/u-reftable-tree.c', + 'unit-tests/u-strbuf.c', + 'unit-tests/u-strcmp-offset.c', 'unit-tests/u-strvec.c', ] clar_sources = [ 'unit-tests/clar/clar.c', 'unit-tests/unit-test.c', + 'unit-tests/lib-oid.c' ] clar_decls_h = custom_target( @@ -35,19 +47,11 @@ clar_sources += custom_target( clar_unit_tests = executable('unit-tests', sources: clar_sources + clar_test_suites, - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], ) test('unit-tests', clar_unit_tests) unit_test_programs = [ - 'unit-tests/t-example-decorate.c', - 'unit-tests/t-hash.c', - 'unit-tests/t-hashmap.c', - 'unit-tests/t-mem-pool.c', - 'unit-tests/t-oid-array.c', - 'unit-tests/t-oidmap.c', - 'unit-tests/t-oidtree.c', - 'unit-tests/t-prio-queue.c', 'unit-tests/t-reftable-basics.c', 'unit-tests/t-reftable-block.c', 'unit-tests/t-reftable-merged.c', @@ -56,9 +60,6 @@ unit_test_programs = [ 'unit-tests/t-reftable-readwrite.c', 'unit-tests/t-reftable-record.c', 'unit-tests/t-reftable-stack.c', - 'unit-tests/t-reftable-tree.c', - 'unit-tests/t-strbuf.c', - 'unit-tests/t-strcmp-offset.c', 'unit-tests/t-trailer.c', 'unit-tests/t-urlmatch-normalization.c', ] @@ -68,11 +69,10 @@ foreach unit_test_program : unit_test_programs unit_test = executable(unit_test_name, sources: [ 'unit-tests/test-lib.c', - 'unit-tests/lib-oid.c', 'unit-tests/lib-reftable.c', unit_test_program, ], - dependencies: [libgit, common_main], + dependencies: [libgit_commonmain], ) test(unit_test_name, unit_test, workdir: meson.current_source_dir(), @@ -500,6 +500,7 @@ integration_tests = [ 't4067-diff-partial-clone.sh', 't4068-diff-symmetric-merge-base.sh', 't4069-remerge-diff.sh', + 't4070-diff-pairs.sh', 't4100-apply-stat.sh', 't4101-apply-nonl.sh', 't4102-apply-rename.sh', @@ -721,12 +722,15 @@ integration_tests = [ 't5617-clone-submodules-remote.sh', 't5618-alternate-refs.sh', 't5619-clone-local-ambiguous-transport.sh', + 't5620-backfill.sh', + 't5621-clone-revision.sh', 't5700-protocol-v1.sh', 't5701-git-serve.sh', 't5702-protocol-v2.sh', 't5703-upload-pack-ref-in-want.sh', 't5704-protocol-violations.sh', 't5705-session-id-in-capabilities.sh', + 't5710-promisor-remote-capability.sh', 't5730-protocol-v2-bundle-uri-file.sh', 't5731-protocol-v2-bundle-uri-git.sh', 't5732-protocol-v2-bundle-uri-http.sh', @@ -829,6 +833,7 @@ integration_tests = [ 't6500-gc.sh', 't6501-freshen-objects.sh', 't6600-test-reach.sh', + 't6601-path-walk.sh', 't6700-tree-depth.sh', 't7001-mv.sh', 't7002-mv-sparse-checkout.sh', diff --git a/t/perf/Makefile b/t/perf/Makefile index e4808aebed..9b3090c4ed 100644 --- a/t/perf/Makefile +++ b/t/perf/Makefile @@ -1,10 +1,13 @@ +# The default target of this Makefile is... +all:: + # Import tree-wide shared Makefile behavior and libraries include ../../shared.mak -include ../../config.mak export GIT_TEST_OPTIONS -all: test-lint perf +all:: test-lint perf perf: pre-clean ./run diff --git a/t/perf/p5313-pack-objects.sh b/t/perf/p5313-pack-objects.sh new file mode 100755 index 0000000000..be5229a0ec --- /dev/null +++ b/t/perf/p5313-pack-objects.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +test_description='Tests pack performance using bitmaps' +. ./perf-lib.sh + +GIT_TEST_PASSING_SANITIZE_LEAK=0 +export GIT_TEST_PASSING_SANITIZE_LEAK + +test_perf_large_repo + +test_expect_success 'create rev input' ' + cat >in-thin <<-EOF && + $(git rev-parse HEAD) + ^$(git rev-parse HEAD~1) + EOF + + cat >in-big <<-EOF && + $(git rev-parse HEAD) + ^$(git rev-parse HEAD~1000) + EOF + + cat >in-shallow <<-EOF + $(git rev-parse HEAD) + --shallow $(git rev-parse HEAD) + EOF +' + +for version in 1 2 +do + export version + + test_perf "thin pack with version $version" ' + git pack-objects --thin --stdout --revs --sparse \ + --name-hash-version=$version <in-thin >out + ' + + test_size "thin pack size with version $version" ' + test_file_size out + ' + + test_perf "big pack with version $version" ' + git pack-objects --stdout --revs --sparse \ + --name-hash-version=$version <in-big >out + ' + + test_size "big pack size with version $version" ' + test_file_size out + ' + + test_perf "shallow fetch pack with version $version" ' + git pack-objects --stdout --revs --sparse --shallow \ + --name-hash-version=$version <in-shallow >out + ' + + test_size "shallow pack size with version $version" ' + test_file_size out + ' + + test_perf "repack with version $version" ' + git repack -adf --name-hash-version=$version + ' + + test_size "repack size with version $version" ' + gitdir=$(git rev-parse --git-dir) && + pack=$(ls $gitdir/objects/pack/pack-*.pack) && + test_file_size "$pack" + ' +done + +test_done diff --git a/t/perf/p5314-name-hash.sh b/t/perf/p5314-name-hash.sh new file mode 100755 index 0000000000..4ef0ba7711 --- /dev/null +++ b/t/perf/p5314-name-hash.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +test_description='Tests pack performance using bitmaps' +. ./perf-lib.sh + +GIT_TEST_PASSING_SANITIZE_LEAK=0 +export GIT_TEST_PASSING_SANITIZE_LEAK + +test_perf_large_repo + +test_size 'paths at head' ' + git ls-tree -r --name-only HEAD >path-list && + wc -l <path-list && + test-tool name-hash <path-list >name-hashes +' + +for version in 1 2 +do + test_size "distinct hash value: v$version" ' + awk "{ print \$$version; }" <name-hashes | sort | \ + uniq -c >name-hash-count && + wc -l <name-hash-count + ' + + test_size "maximum multiplicity: v$version" ' + sort -nr <name-hash-count | head -n 1 | \ + awk "{ print \$1; }" + ' +done + +test_done diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 72a0c2e7d4..c49d9e0d38 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -586,6 +586,18 @@ test_expect_success 'GIT_DEFAULT_HASH overrides init.defaultObjectFormat' ' echo sha256 >expected ' +for hash in sha1 sha256 +do + test_expect_success "reinit repository with GIT_DEFAULT_HASH=$hash does not change format" ' + test_when_finished "rm -rf repo" && + git init repo && + git -C repo rev-parse --show-object-format >expect && + GIT_DEFAULT_HASH=$hash git init repo && + git -C repo rev-parse --show-object-format >actual && + test_cmp expect actual + ' +done + test_expect_success 'extensions.objectFormat is not allowed with repo version 0' ' test_when_finished "rm -rf explicit-v0" && git init --object-format=sha256 explicit-v0 && @@ -697,6 +709,15 @@ do git -C refformat rev-parse --show-ref-format >actual && test_cmp expect actual ' + + test_expect_success "reinit repository with GIT_DEFAULT_REF_FORMAT=$format does not change format" ' + test_when_finished "rm -rf refformat" && + git init refformat && + git -C refformat rev-parse --show-ref-format >expect && + GIT_DEFAULT_REF_FORMAT=$format git init refformat && + git -C refformat rev-parse --show-ref-format >actual && + test_cmp expect actual + ' done test_expect_success "--ref-format= overrides GIT_DEFAULT_REF_FORMAT" ' @@ -861,15 +882,6 @@ test_expect_success 're-init with includeIf.onbranch condition' ' test_cmp expect actual ' -test_expect_success 're-init with includeIf.onbranch condition' ' - test_when_finished "rm -rf repo" && - git init repo && - git -c includeIf.onbranch:nonexistent.path=/does/not/exist init repo && - echo $GIT_DEFAULT_REF_FORMAT >expect && - git -C repo rev-parse --show-ref-format >actual && - test_cmp expect actual -' - test_expect_success 're-init skips non-matching includeIf.onbranch' ' test_when_finished "rm -rf repo config" && cat >config <<-EOF && diff --git a/t/t0012-help.sh b/t/t0012-help.sh index 1d273d91c2..d3a0967e9d 100755 --- a/t/t0012-help.sh +++ b/t/t0012-help.sh @@ -255,8 +255,9 @@ do ( GIT_CEILING_DIRECTORIES=$(pwd) && export GIT_CEILING_DIRECTORIES && - test_expect_code 129 git -C sub $builtin -h >output 2>&1 + test_expect_code 129 git -C sub $builtin -h >output 2>err ) && + test_must_be_empty err && test_grep usage output ' done <builtins diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index dbb2e73bcd..8545cdfab5 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -592,17 +592,19 @@ test_lazy_prereq CAN_EXEC_IN_PWD ' ./git rev-parse ' +test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD 'setup runtime prefix' ' + mkdir -p pretend/bin && + cp "$GIT_EXEC_PATH"/git$X pretend/bin/ +' + test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD 'RUNTIME_PREFIX works' ' - mkdir -p pretend/bin pretend/libexec/git-core && + mkdir -p pretend/libexec/git-core && echo "echo HERE" | write_script pretend/libexec/git-core/git-here && - cp "$GIT_EXEC_PATH"/git$X pretend/bin/ && GIT_EXEC_PATH= ./pretend/bin/git here >actual && echo HERE >expect && test_cmp expect actual' test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD '%(prefix)/ works' ' - mkdir -p pretend/bin && - cp "$GIT_EXEC_PATH"/git$X pretend/bin/ && git config yes.path "%(prefix)/yes" && GIT_EXEC_PATH= ./pretend/bin/git config --path yes.path >actual && echo "$(pwd)/pretend/yes" >expect && diff --git a/t/t0091-bugreport.sh b/t/t0091-bugreport.sh index e11d819b62..e38ca7a901 100755 --- a/t/t0091-bugreport.sh +++ b/t/t0091-bugreport.sh @@ -47,7 +47,8 @@ test_expect_success 'sanity check "System Info" section' ' # This is bound to differ from environment to environment, # so we just do some rather high-level checks. grep "uname: ." system && - grep "compiler info: ." system + grep "compiler info: ." system && + grep "zlib." system ' test_expect_success 'dies if file with same name as report already exists' ' diff --git a/t/t0210-trace2-normal.sh b/t/t0210-trace2-normal.sh index eff9a59dbd..4287ed3fbb 100755 --- a/t/t0210-trace2-normal.sh +++ b/t/t0210-trace2-normal.sh @@ -243,6 +243,15 @@ test_expect_success 'bug messages followed by BUG() are written to trace2' ' test_cmp expect actual ' +test_expect_success 'a valueless true configuration variable is handled' ' + test_when_finished "rm -f trace2.normal actual expect" && + echo >expect && + GIT_TRACE2="$(pwd)/trace2.normal" \ + GIT_TRACE2_CONFIG_PARAMS=foo.true \ + git -c foo.true config foo.true >actual && + test_cmp expect actual +' + sane_unset GIT_TRACE2_BRIEF # Now test without environment variables and get all Trace2 settings diff --git a/t/t0450-txt-doc-vs-help.sh b/t/t0450-txt-doc-vs-help.sh index 853101b86e..2f7504ae7e 100755 --- a/t/t0450-txt-doc-vs-help.sh +++ b/t/t0450-txt-doc-vs-help.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='assert (unbuilt) Documentation/*.txt and -h output +test_description='assert (unbuilt) Documentation/*.adoc and -h output Run this with --debug to see a summary of where we still fail to make the two versions consistent with one another.' @@ -11,11 +11,11 @@ test_expect_success 'setup: list of builtins' ' git --list-cmds=builtins >builtins ' -test_expect_success 'list of txt and help mismatches is sorted' ' - sort -u "$TEST_DIRECTORY"/t0450/txt-help-mismatches >expect && - if ! test_cmp expect "$TEST_DIRECTORY"/t0450/txt-help-mismatches +test_expect_success 'list of adoc and help mismatches is sorted' ' + sort -u "$TEST_DIRECTORY"/t0450/adoc-help-mismatches >expect && + if ! test_cmp expect "$TEST_DIRECTORY"/t0450/adoc-help-mismatches then - BUG "please keep the list of txt and help mismatches sorted" + BUG "please keep the list of adoc and help mismatches sorted" fi ' @@ -40,20 +40,20 @@ help_to_synopsis () { echo "$out" } -builtin_to_txt () { - echo "$GIT_BUILD_DIR/Documentation/git-$1.txt" +builtin_to_adoc () { + echo "$GIT_BUILD_DIR/Documentation/git-$1.adoc" } -txt_to_synopsis () { +adoc_to_synopsis () { builtin="$1" && out_dir="out/$builtin" && - out="$out_dir/txt.synopsis" && + out="$out_dir/adoc.synopsis" && if test -f "$out" then echo "$out" && return 0 fi && - b2t="$(builtin_to_txt "$builtin")" && + b2t="$(builtin_to_adoc "$builtin")" && sed -n \ -E '/^\[(verse|synopsis)\]$/,/^$/ { /^$/d; @@ -109,29 +109,29 @@ do fi ' - txt="$(builtin_to_txt "$builtin")" && - preq="$(echo BUILTIN_TXT_$builtin | tr '[:lower:]-' '[:upper:]_')" && + adoc="$(builtin_to_adoc "$builtin")" && + preq="$(echo BUILTIN_ADOC_$builtin | tr '[:lower:]-' '[:upper:]_')" && - if test -f "$txt" + if test -f "$adoc" then test_set_prereq "$preq" fi && - # *.txt output assertions - test_expect_success "$preq" "$builtin *.txt SYNOPSIS has dashed labels" ' - check_dashed_labels "$(txt_to_synopsis "$builtin")" + # *.adoc output assertions + test_expect_success "$preq" "$builtin *.adoc SYNOPSIS has dashed labels" ' + check_dashed_labels "$(adoc_to_synopsis "$builtin")" ' - # *.txt output consistency assertions + # *.adoc output consistency assertions result= - if grep -q "^$builtin$" "$TEST_DIRECTORY"/t0450/txt-help-mismatches + if grep -q "^$builtin$" "$TEST_DIRECTORY"/t0450/adoc-help-mismatches then result=failure else result=success fi && test_expect_$result "$preq" "$builtin -h output and SYNOPSIS agree" ' - t2s="$(txt_to_synopsis "$builtin")" && + t2s="$(adoc_to_synopsis "$builtin")" && if test "$builtin" = "merge-tree" then test_when_finished "rm -f t2s.new" && @@ -140,17 +140,17 @@ do fi && h2s="$(help_to_synopsis "$builtin")" && - # The *.txt and -h use different spacing for the + # The *.adoc and -h use different spacing for the # alignment of continued usage output, normalize it. - align_after_nl "$builtin" <"$t2s" >txt && + align_after_nl "$builtin" <"$t2s" >adoc && align_after_nl "$builtin" <"$h2s" >help && - test_cmp txt help + test_cmp adoc help ' - if test_have_prereq "$preq" && test -e txt && test -e help + if test_have_prereq "$preq" && test -e adoc && test -e help then test_debug ' - if test_cmp txt help >cmp 2>/dev/null + if test_cmp adoc help >cmp 2>/dev/null then echo "=== DONE: $builtin ===" else @@ -161,7 +161,7 @@ do # Not in test_expect_success in case --run is being # used with --debug - rm -f txt help tmp 2>/dev/null + rm -f adoc help tmp 2>/dev/null fi done <builtins diff --git a/t/t0450/txt-help-mismatches b/t/t0450/adoc-help-mismatches index 28003f18c9..c4a15fd0cb 100644 --- a/t/t0450/txt-help-mismatches +++ b/t/t0450/adoc-help-mismatches @@ -45,7 +45,6 @@ rebase remote remote-ext remote-fd -repack reset restore rev-parse diff --git a/t/t0602-reffiles-fsck.sh b/t/t0602-reffiles-fsck.sh index d4a08b823b..9d1dc2144c 100755 --- a/t/t0602-reffiles-fsck.sh +++ b/t/t0602-reffiles-fsck.sh @@ -14,222 +14,229 @@ test_expect_success 'ref name should be checked' ' git init repo && branch_dir_prefix=.git/refs/heads && tag_dir_prefix=.git/refs/tags && - cd repo && - - git commit --allow-empty -m initial && - git checkout -b default-branch && - git tag default-tag && - git tag multi_hierarchy/default-tag && - - cp $branch_dir_prefix/default-branch $branch_dir_prefix/@ && - git refs verify 2>err && - test_must_be_empty err && - rm $branch_dir_prefix/@ && - - cp $tag_dir_prefix/default-tag $tag_dir_prefix/tag-1.lock && - git refs verify 2>err && - rm $tag_dir_prefix/tag-1.lock && - test_must_be_empty err && - - cp $tag_dir_prefix/default-tag $tag_dir_prefix/.lock && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/tags/.lock: badRefName: invalid refname format - EOF - rm $tag_dir_prefix/.lock && - test_cmp expect err && - - for refname in ".refname-starts-with-dot" "~refname-has-stride" - do - cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname" && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/$refname: badRefName: invalid refname format - EOF - rm "$branch_dir_prefix/$refname" && - test_cmp expect err || return 1 - done && + ( + cd repo && - for refname in ".refname-starts-with-dot" "~refname-has-stride" - do - cp $tag_dir_prefix/default-tag "$tag_dir_prefix/$refname" && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/tags/$refname: badRefName: invalid refname format - EOF - rm "$tag_dir_prefix/$refname" && - test_cmp expect err || return 1 - done && + git commit --allow-empty -m initial && + git checkout -b default-branch && + git tag default-tag && + git tag multi_hierarchy/default-tag && - for refname in ".refname-starts-with-dot" "~refname-has-stride" - do - cp $tag_dir_prefix/multi_hierarchy/default-tag "$tag_dir_prefix/multi_hierarchy/$refname" && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/tags/multi_hierarchy/$refname: badRefName: invalid refname format - EOF - rm "$tag_dir_prefix/multi_hierarchy/$refname" && - test_cmp expect err || return 1 - done && + cp $branch_dir_prefix/default-branch $branch_dir_prefix/@ && + git refs verify 2>err && + test_must_be_empty err && + rm $branch_dir_prefix/@ && + + cp $tag_dir_prefix/default-tag $tag_dir_prefix/tag-1.lock && + git refs verify 2>err && + rm $tag_dir_prefix/tag-1.lock && + test_must_be_empty err && - for refname in ".refname-starts-with-dot" "~refname-has-stride" - do - mkdir "$branch_dir_prefix/$refname" && - cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname/default-branch" && + cp $tag_dir_prefix/default-tag $tag_dir_prefix/.lock && test_must_fail git refs verify 2>err && cat >expect <<-EOF && - error: refs/heads/$refname/default-branch: badRefName: invalid refname format + error: refs/tags/.lock: badRefName: invalid refname format EOF - rm -r "$branch_dir_prefix/$refname" && - test_cmp expect err || return 1 - done + rm $tag_dir_prefix/.lock && + test_cmp expect err && + + for refname in ".refname-starts-with-dot" "~refname-has-stride" + do + cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname" && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/$refname: badRefName: invalid refname format + EOF + rm "$branch_dir_prefix/$refname" && + test_cmp expect err || return 1 + done && + + for refname in ".refname-starts-with-dot" "~refname-has-stride" + do + cp $tag_dir_prefix/default-tag "$tag_dir_prefix/$refname" && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/tags/$refname: badRefName: invalid refname format + EOF + rm "$tag_dir_prefix/$refname" && + test_cmp expect err || return 1 + done && + + for refname in ".refname-starts-with-dot" "~refname-has-stride" + do + cp $tag_dir_prefix/multi_hierarchy/default-tag "$tag_dir_prefix/multi_hierarchy/$refname" && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/tags/multi_hierarchy/$refname: badRefName: invalid refname format + EOF + rm "$tag_dir_prefix/multi_hierarchy/$refname" && + test_cmp expect err || return 1 + done && + + for refname in ".refname-starts-with-dot" "~refname-has-stride" + do + mkdir "$branch_dir_prefix/$refname" && + cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname/default-branch" && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/$refname/default-branch: badRefName: invalid refname format + EOF + rm -r "$branch_dir_prefix/$refname" && + test_cmp expect err || return 1 + done + ) ' test_expect_success 'ref name check should be adapted into fsck messages' ' test_when_finished "rm -rf repo" && git init repo && branch_dir_prefix=.git/refs/heads && - cd repo && - git commit --allow-empty -m initial && - git checkout -b branch-1 && - - cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 && - git -c fsck.badRefName=warn refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/.branch-1: badRefName: invalid refname format - EOF - rm $branch_dir_prefix/.branch-1 && - test_cmp expect err && - - cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 && - git -c fsck.badRefName=ignore refs verify 2>err && - test_must_be_empty err + ( + cd repo && + git commit --allow-empty -m initial && + git checkout -b branch-1 && + + cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 && + git -c fsck.badRefName=warn refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/.branch-1: badRefName: invalid refname format + EOF + rm $branch_dir_prefix/.branch-1 && + test_cmp expect err && + + cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 && + git -c fsck.badRefName=ignore refs verify 2>err && + test_must_be_empty err + ) ' test_expect_success 'ref name check should work for multiple worktrees' ' test_when_finished "rm -rf repo" && git init repo && - - cd repo && - test_commit initial && - git checkout -b branch-1 && - test_commit second && - git checkout -b branch-2 && - test_commit third && - git checkout -b branch-3 && - git worktree add ./worktree-1 branch-1 && - git worktree add ./worktree-2 branch-2 && - worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && - worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && - ( - cd worktree-1 && - git update-ref refs/worktree/branch-4 refs/heads/branch-3 - ) && - ( - cd worktree-2 && - git update-ref refs/worktree/branch-4 refs/heads/branch-3 - ) && - - cp $worktree1_refdir_prefix/branch-4 $worktree1_refdir_prefix/'\'' branch-5'\'' && - cp $worktree2_refdir_prefix/branch-4 $worktree2_refdir_prefix/'\''~branch-6'\'' && - - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format - error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format - EOF - sort err >sorted_err && - test_cmp expect sorted_err && - - for worktree in "worktree-1" "worktree-2" - do + cd repo && + test_commit initial && + git checkout -b branch-1 && + test_commit second && + git checkout -b branch-2 && + test_commit third && + git checkout -b branch-3 && + git worktree add ./worktree-1 branch-1 && + git worktree add ./worktree-2 branch-2 && + worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && + worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && + ( - cd $worktree && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format - error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format - EOF - sort err >sorted_err && - test_cmp expect sorted_err || return 1 - ) - done + cd worktree-1 && + git update-ref refs/worktree/branch-4 refs/heads/branch-3 + ) && + ( + cd worktree-2 && + git update-ref refs/worktree/branch-4 refs/heads/branch-3 + ) && + + cp $worktree1_refdir_prefix/branch-4 $worktree1_refdir_prefix/'\'' branch-5'\'' && + cp $worktree2_refdir_prefix/branch-4 $worktree2_refdir_prefix/'\''~branch-6'\'' && + + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format + error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format + EOF + sort err >sorted_err && + test_cmp expect sorted_err && + + for worktree in "worktree-1" "worktree-2" + do + ( + cd $worktree && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format + error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format + EOF + sort err >sorted_err && + test_cmp expect sorted_err || return 1 + ) + done + ) ' test_expect_success 'regular ref content should be checked (individual)' ' test_when_finished "rm -rf repo" && git init repo && branch_dir_prefix=.git/refs/heads && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && - git refs verify 2>err && - test_must_be_empty err && + git refs verify 2>err && + test_must_be_empty err && - for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas" - do - printf "%s" $bad_content >$branch_dir_prefix/branch-bad && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/branch-bad: badRefContent: $bad_content - EOF - rm $branch_dir_prefix/branch-bad && - test_cmp expect err || return 1 - done && + for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas" + do + printf "%s" $bad_content >$branch_dir_prefix/branch-bad && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/branch-bad: badRefContent: $bad_content + EOF + rm $branch_dir_prefix/branch-bad && + test_cmp expect err || return 1 + done && - for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas" - do - printf "%s" $bad_content >$branch_dir_prefix/a/b/branch-bad && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/a/b/branch-bad: badRefContent: $bad_content - EOF - rm $branch_dir_prefix/a/b/branch-bad && - test_cmp expect err || return 1 - done && - - printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end - EOF - rm $branch_dir_prefix/branch-no-newline && - test_cmp expect err && - - for trailing_content in " garbage" " more garbage" - do - printf "%s" "$(git rev-parse main)$trailing_content" >$branch_dir_prefix/branch-garbage && + for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas" + do + printf "%s" $bad_content >$branch_dir_prefix/a/b/branch-bad && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/a/b/branch-bad: badRefContent: $bad_content + EOF + rm $branch_dir_prefix/a/b/branch-bad && + test_cmp expect err || return 1 + done && + + printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline && git refs verify 2>err && cat >expect <<-EOF && - warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\'' + warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end EOF - rm $branch_dir_prefix/branch-garbage && - test_cmp expect err || return 1 - done && + rm $branch_dir_prefix/branch-no-newline && + test_cmp expect err && - printf "%s\n\n\n" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\'' + for trailing_content in " garbage" " more garbage" + do + printf "%s" "$(git rev-parse main)$trailing_content" >$branch_dir_prefix/branch-garbage && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\'' + EOF + rm $branch_dir_prefix/branch-garbage && + test_cmp expect err || return 1 + done && + printf "%s\n\n\n" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\'' - '\'' - EOF - rm $branch_dir_prefix/branch-garbage-special && - test_cmp expect err && - printf "%s\n\n\n garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\'' + '\'' + EOF + rm $branch_dir_prefix/branch-garbage-special && + test_cmp expect err && + + printf "%s\n\n\n garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\'' - garbage'\'' - EOF - rm $branch_dir_prefix/branch-garbage-special && - test_cmp expect err + garbage'\'' + EOF + rm $branch_dir_prefix/branch-garbage-special && + test_cmp expect err + ) ' test_expect_success 'regular ref content should be checked (aggregate)' ' @@ -237,99 +244,103 @@ test_expect_success 'regular ref content should be checked (aggregate)' ' git init repo && branch_dir_prefix=.git/refs/heads && tag_dir_prefix=.git/refs/tags && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && - - bad_content_1=$(git rev-parse main)x && - bad_content_2=xfsazqfxcadas && - bad_content_3=Xfsazqfxcadas && - printf "%s" $bad_content_1 >$tag_dir_prefix/tag-bad-1 && - printf "%s" $bad_content_2 >$tag_dir_prefix/tag-bad-2 && - printf "%s" $bad_content_3 >$branch_dir_prefix/a/b/branch-bad && - printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline && - printf "%s garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage && - - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/a/b/branch-bad: badRefContent: $bad_content_3 - error: refs/tags/tag-bad-1: badRefContent: $bad_content_1 - error: refs/tags/tag-bad-2: badRefContent: $bad_content_2 - warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\'' - warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end - EOF - sort err >sorted_err && - test_cmp expect sorted_err + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + bad_content_1=$(git rev-parse main)x && + bad_content_2=xfsazqfxcadas && + bad_content_3=Xfsazqfxcadas && + printf "%s" $bad_content_1 >$tag_dir_prefix/tag-bad-1 && + printf "%s" $bad_content_2 >$tag_dir_prefix/tag-bad-2 && + printf "%s" $bad_content_3 >$branch_dir_prefix/a/b/branch-bad && + printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline && + printf "%s garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage && + + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/a/b/branch-bad: badRefContent: $bad_content_3 + error: refs/tags/tag-bad-1: badRefContent: $bad_content_1 + error: refs/tags/tag-bad-2: badRefContent: $bad_content_2 + warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\'' + warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end + EOF + sort err >sorted_err && + test_cmp expect sorted_err + ) ' test_expect_success 'textual symref content should be checked (individual)' ' test_when_finished "rm -rf repo" && git init repo && branch_dir_prefix=.git/refs/heads && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + for good_referent in "refs/heads/branch" "HEAD" + do + printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good && + git refs verify 2>err && + rm $branch_dir_prefix/branch-good && + test_must_be_empty err || return 1 + done && + + for bad_referent in "refs/heads/.branch" "refs/heads/~branch" "refs/heads/?branch" + do + printf "ref: %s\n" $bad_referent >$branch_dir_prefix/branch-bad && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/branch-bad: badReferentName: points to invalid refname '\''$bad_referent'\'' + EOF + rm $branch_dir_prefix/branch-bad && + test_cmp expect err || return 1 + done && - for good_referent in "refs/heads/branch" "HEAD" - do - printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good && + printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline && git refs verify 2>err && - rm $branch_dir_prefix/branch-good && - test_must_be_empty err || return 1 - done && + cat >expect <<-EOF && + warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end + EOF + rm $branch_dir_prefix/branch-no-newline && + test_cmp expect err && - for bad_referent in "refs/heads/.branch" "refs/heads/~branch" "refs/heads/?branch" - do - printf "ref: %s\n" $bad_referent >$branch_dir_prefix/branch-bad && - test_must_fail git refs verify 2>err && + printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end + warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines + EOF + rm $branch_dir_prefix/a/b/branch-trailing-1 && + test_cmp expect err && + + printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines + EOF + rm $branch_dir_prefix/a/b/branch-trailing-2 && + test_cmp expect err && + + printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 && + git refs verify 2>err && cat >expect <<-EOF && - error: refs/heads/branch-bad: badReferentName: points to invalid refname '\''$bad_referent'\'' - EOF - rm $branch_dir_prefix/branch-bad && - test_cmp expect err || return 1 - done && - - printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end - EOF - rm $branch_dir_prefix/branch-no-newline && - test_cmp expect err && - - printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end - warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines - EOF - rm $branch_dir_prefix/a/b/branch-trailing-1 && - test_cmp expect err && - - printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines - EOF - rm $branch_dir_prefix/a/b/branch-trailing-2 && - test_cmp expect err && - - printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines - EOF - rm $branch_dir_prefix/a/b/branch-trailing-3 && - test_cmp expect err && - - printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end - warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines - EOF - rm $branch_dir_prefix/a/b/branch-complicated && - test_cmp expect err + warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines + EOF + rm $branch_dir_prefix/a/b/branch-trailing-3 && + test_cmp expect err && + + printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end + warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines + EOF + rm $branch_dir_prefix/a/b/branch-complicated && + test_cmp expect err + ) ' test_expect_success 'textual symref content should be checked (aggregate)' ' @@ -337,32 +348,34 @@ test_expect_success 'textual symref content should be checked (aggregate)' ' git init repo && branch_dir_prefix=.git/refs/heads && tag_dir_prefix=.git/refs/tags && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && - - printf "ref: refs/heads/branch\n" >$branch_dir_prefix/branch-good && - printf "ref: HEAD\n" >$branch_dir_prefix/branch-head && - printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline-1 && - printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 && - printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 && - printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 && - printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated && - printf "ref: refs/heads/.branch\n" >$branch_dir_prefix/branch-bad-1 && - - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/branch-bad-1: badReferentName: points to invalid refname '\''refs/heads/.branch'\'' - warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end - warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines - warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end - warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines - warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines - warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines - warning: refs/heads/branch-no-newline-1: refMissingNewline: misses LF at the end - EOF - sort err >sorted_err && - test_cmp expect sorted_err + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + printf "ref: refs/heads/branch\n" >$branch_dir_prefix/branch-good && + printf "ref: HEAD\n" >$branch_dir_prefix/branch-head && + printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline-1 && + printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 && + printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 && + printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 && + printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated && + printf "ref: refs/heads/.branch\n" >$branch_dir_prefix/branch-bad-1 && + + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/branch-bad-1: badReferentName: points to invalid refname '\''refs/heads/.branch'\'' + warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end + warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines + warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end + warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines + warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines + warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines + warning: refs/heads/branch-no-newline-1: refMissingNewline: misses LF at the end + EOF + sort err >sorted_err && + test_cmp expect sorted_err + ) ' test_expect_success 'the target of the textual symref should be checked' ' @@ -370,230 +383,490 @@ test_expect_success 'the target of the textual symref should be checked' ' git init repo && branch_dir_prefix=.git/refs/heads && tag_dir_prefix=.git/refs/tags && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + for good_referent in "refs/heads/branch" "HEAD" "refs/tags/tag" + do + printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good && + git refs verify 2>err && + rm $branch_dir_prefix/branch-good && + test_must_be_empty err || return 1 + done && + + for nonref_referent in "refs-back/heads/branch" "refs-back/tags/tag" "reflogs/refs/heads/branch" + do + printf "ref: %s\n" $nonref_referent >$branch_dir_prefix/branch-bad-1 && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-bad-1: symrefTargetIsNotARef: points to non-ref target '\''$nonref_referent'\'' + EOF + rm $branch_dir_prefix/branch-bad-1 && + test_cmp expect err || return 1 + done + ) +' + +test_expect_success SYMLINKS 'symlink symref content should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + branch_dir_prefix=.git/refs/heads && + tag_dir_prefix=.git/refs/tags && + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && - for good_referent in "refs/heads/branch" "HEAD" "refs/tags/tag" - do - printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good && + ln -sf ./main $branch_dir_prefix/branch-symbolic-good && git refs verify 2>err && - rm $branch_dir_prefix/branch-good && - test_must_be_empty err || return 1 - done && + cat >expect <<-EOF && + warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref + EOF + rm $branch_dir_prefix/branch-symbolic-good && + test_cmp expect err && - for nonref_referent in "refs-back/heads/branch" "refs-back/tags/tag" "reflogs/refs/heads/branch" - do - printf "ref: %s\n" $nonref_referent >$branch_dir_prefix/branch-bad-1 && + ln -sf ../../logs/branch-escape $branch_dir_prefix/branch-symbolic && git refs verify 2>err && cat >expect <<-EOF && - warning: refs/heads/branch-bad-1: symrefTargetIsNotARef: points to non-ref target '\''$nonref_referent'\'' + warning: refs/heads/branch-symbolic: symlinkRef: use deprecated symbolic link for symref + warning: refs/heads/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\'' + EOF + rm $branch_dir_prefix/branch-symbolic && + test_cmp expect err && + + ln -sf ./"branch " $branch_dir_prefix/branch-symbolic-bad && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-symbolic-bad: symlinkRef: use deprecated symbolic link for symref + error: refs/heads/branch-symbolic-bad: badReferentName: points to invalid refname '\''refs/heads/branch '\'' + EOF + rm $branch_dir_prefix/branch-symbolic-bad && + test_cmp expect err && + + ln -sf ./".tag" $tag_dir_prefix/tag-symbolic-1 && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/tags/tag-symbolic-1: symlinkRef: use deprecated symbolic link for symref + error: refs/tags/tag-symbolic-1: badReferentName: points to invalid refname '\''refs/tags/.tag'\'' EOF - rm $branch_dir_prefix/branch-bad-1 && - test_cmp expect err || return 1 - done + rm $tag_dir_prefix/tag-symbolic-1 && + test_cmp expect err + ) ' -test_expect_success SYMLINKS 'symlink symref content should be checked' ' +test_expect_success SYMLINKS 'symlink symref content should be checked (worktree)' ' test_when_finished "rm -rf repo" && git init repo && - branch_dir_prefix=.git/refs/heads && - tag_dir_prefix=.git/refs/tags && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && - - ln -sf ./main $branch_dir_prefix/branch-symbolic-good && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref - EOF - rm $branch_dir_prefix/branch-symbolic-good && - test_cmp expect err && - - ln -sf ../../logs/branch-escape $branch_dir_prefix/branch-symbolic && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-symbolic: symlinkRef: use deprecated symbolic link for symref - warning: refs/heads/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\'' - EOF - rm $branch_dir_prefix/branch-symbolic && - test_cmp expect err && - - ln -sf ./"branch " $branch_dir_prefix/branch-symbolic-bad && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-symbolic-bad: symlinkRef: use deprecated symbolic link for symref - error: refs/heads/branch-symbolic-bad: badReferentName: points to invalid refname '\''refs/heads/branch '\'' - EOF - rm $branch_dir_prefix/branch-symbolic-bad && - test_cmp expect err && - - ln -sf ./".tag" $tag_dir_prefix/tag-symbolic-1 && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/tags/tag-symbolic-1: symlinkRef: use deprecated symbolic link for symref - error: refs/tags/tag-symbolic-1: badReferentName: points to invalid refname '\''refs/tags/.tag'\'' - EOF - rm $tag_dir_prefix/tag-symbolic-1 && - test_cmp expect err + ( + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git branch branch-3 && + git worktree add ./worktree-1 branch-2 && + git worktree add ./worktree-2 branch-3 && + main_worktree_refdir_prefix=.git/refs/heads && + worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && + worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && + + ( + cd worktree-1 && + git update-ref refs/worktree/branch-4 refs/heads/branch-1 + ) && + ( + cd worktree-2 && + git update-ref refs/worktree/branch-4 refs/heads/branch-1 + ) && + + ln -sf ../../../../refs/heads/good-branch $worktree1_refdir_prefix/branch-symbolic-good && + git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-1/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref + EOF + rm $worktree1_refdir_prefix/branch-symbolic-good && + test_cmp expect err && + + ln -sf ../../../../worktrees/worktree-1/good-branch $worktree2_refdir_prefix/branch-symbolic-good && + git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-2/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref + EOF + rm $worktree2_refdir_prefix/branch-symbolic-good && + test_cmp expect err && + + ln -sf ../../worktrees/worktree-2/good-branch $main_worktree_refdir_prefix/branch-symbolic-good && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref + EOF + rm $main_worktree_refdir_prefix/branch-symbolic-good && + test_cmp expect err && + + ln -sf ../../../../logs/branch-escape $worktree1_refdir_prefix/branch-symbolic && + git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symlinkRef: use deprecated symbolic link for symref + warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\'' + EOF + rm $worktree1_refdir_prefix/branch-symbolic && + test_cmp expect err && + + for bad_referent_name in ".tag" "branch " + do + ln -sf ./"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref + error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-1/refs/worktree/$bad_referent_name'\'' + EOF + rm $worktree1_refdir_prefix/bad-symbolic && + test_cmp expect err && + + ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref + error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\'' + EOF + rm $worktree1_refdir_prefix/bad-symbolic && + test_cmp expect err && + + ln -sf ./"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref + error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-2/refs/worktree/$bad_referent_name'\'' + EOF + rm $worktree2_refdir_prefix/bad-symbolic && + test_cmp expect err && + + ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref + error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\'' + EOF + rm $worktree2_refdir_prefix/bad-symbolic && + test_cmp expect err || return 1 + done + ) ' -test_expect_success SYMLINKS 'symlink symref content should be checked (worktree)' ' +test_expect_success 'ref content checks should work with worktrees' ' test_when_finished "rm -rf repo" && git init repo && - cd repo && - test_commit default && - git branch branch-1 && - git branch branch-2 && - git branch branch-3 && - git worktree add ./worktree-1 branch-2 && - git worktree add ./worktree-2 branch-3 && - main_worktree_refdir_prefix=.git/refs/heads && - worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && - worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && - - ( - cd worktree-1 && - git update-ref refs/worktree/branch-4 refs/heads/branch-1 - ) && ( - cd worktree-2 && - git update-ref refs/worktree/branch-4 refs/heads/branch-1 - ) && - - ln -sf ../../../../refs/heads/good-branch $worktree1_refdir_prefix/branch-symbolic-good && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref - EOF - rm $worktree1_refdir_prefix/branch-symbolic-good && - test_cmp expect err && - - ln -sf ../../../../worktrees/worktree-1/good-branch $worktree2_refdir_prefix/branch-symbolic-good && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-2/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref - EOF - rm $worktree2_refdir_prefix/branch-symbolic-good && - test_cmp expect err && - - ln -sf ../../worktrees/worktree-2/good-branch $main_worktree_refdir_prefix/branch-symbolic-good && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref - EOF - rm $main_worktree_refdir_prefix/branch-symbolic-good && - test_cmp expect err && - - ln -sf ../../../../logs/branch-escape $worktree1_refdir_prefix/branch-symbolic && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symlinkRef: use deprecated symbolic link for symref - warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\'' - EOF - rm $worktree1_refdir_prefix/branch-symbolic && - test_cmp expect err && - - for bad_referent_name in ".tag" "branch " - do - ln -sf ./"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic && - test_must_fail git refs verify 2>err && + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git branch branch-3 && + git worktree add ./worktree-1 branch-2 && + git worktree add ./worktree-2 branch-3 && + worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && + worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && + + ( + cd worktree-1 && + git update-ref refs/worktree/branch-4 refs/heads/branch-1 + ) && + ( + cd worktree-2 && + git update-ref refs/worktree/branch-4 refs/heads/branch-1 + ) && + + for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas" + do + printf "%s" $bad_content >$worktree1_refdir_prefix/bad-branch-1 && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: worktrees/worktree-1/refs/worktree/bad-branch-1: badRefContent: $bad_content + EOF + rm $worktree1_refdir_prefix/bad-branch-1 && + test_cmp expect err || return 1 + done && + + for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas" + do + printf "%s" $bad_content >$worktree2_refdir_prefix/bad-branch-2 && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: worktrees/worktree-2/refs/worktree/bad-branch-2: badRefContent: $bad_content + EOF + rm $worktree2_refdir_prefix/bad-branch-2 && + test_cmp expect err || return 1 + done && + + printf "%s" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-no-newline && + git refs verify 2>err && cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref - error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-1/refs/worktree/$bad_referent_name'\'' + warning: worktrees/worktree-1/refs/worktree/branch-no-newline: refMissingNewline: misses LF at the end EOF - rm $worktree1_refdir_prefix/bad-symbolic && + rm $worktree1_refdir_prefix/branch-no-newline && test_cmp expect err && - ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic && - test_must_fail git refs verify 2>err && + printf "%s garbage" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-garbage && + git refs verify 2>err && cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref - error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\'' + warning: worktrees/worktree-1/refs/worktree/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\'' EOF - rm $worktree1_refdir_prefix/bad-symbolic && - test_cmp expect err && + rm $worktree1_refdir_prefix/branch-garbage && + test_cmp expect err + ) +' - ln -sf ./"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic && +test_expect_success SYMLINKS 'the filetype of packed-refs should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git branch branch-3 && + git pack-refs --all && + + mv .git/packed-refs .git/packed-refs-back && + ln -sf packed-refs-back .git/packed-refs && test_must_fail git refs verify 2>err && cat >expect <<-EOF && - warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref - error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-2/refs/worktree/$bad_referent_name'\'' + error: packed-refs: badRefFiletype: not a regular file but a symlink EOF - rm $worktree2_refdir_prefix/bad-symbolic && + rm .git/packed-refs && test_cmp expect err && - ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic && + mkdir .git/packed-refs && test_must_fail git refs verify 2>err && cat >expect <<-EOF && - warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref - error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\'' + error: packed-refs: badRefFiletype: not a regular file EOF - rm $worktree2_refdir_prefix/bad-symbolic && - test_cmp expect err || return 1 - done + rm -r .git/packed-refs && + test_cmp expect err + ) ' -test_expect_success 'ref content checks should work with worktrees' ' +test_expect_success 'packed-refs header should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + + git refs verify 2>err && + test_must_be_empty err && + + for bad_header in "# pack-refs wit: peeled fully-peeled sorted " \ + "# pack-refs with traits: peeled fully-peeled sorted " \ + "# pack-refs with a: peeled fully-peeled" \ + "# pack-refs with:peeled fully-peeled sorted" + do + printf "%s\n" "$bad_header" >.git/packed-refs && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: packed-refs.header: badPackedRefHeader: '\''$bad_header'\'' does not start with '\''# pack-refs with: '\'' + EOF + rm .git/packed-refs && + test_cmp expect err || return 1 + done + ) +' + +test_expect_success 'packed-refs missing header should not be reported' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + + printf "$(git rev-parse HEAD) refs/heads/main\n" >.git/packed-refs && + git refs verify 2>err && + test_must_be_empty err + ) +' + +test_expect_success 'packed-refs unknown traits should not be reported' ' test_when_finished "rm -rf repo" && git init repo && - cd repo && - test_commit default && - git branch branch-1 && - git branch branch-2 && - git branch branch-3 && - git worktree add ./worktree-1 branch-2 && - git worktree add ./worktree-2 branch-3 && - worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && - worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && + ( + cd repo && + test_commit default && + + printf "# pack-refs with: peeled fully-peeled sorted foo\n" >.git/packed-refs && + git refs verify 2>err && + test_must_be_empty err + ) +' +test_expect_success 'packed-refs content should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && ( - cd worktree-1 && - git update-ref refs/worktree/branch-4 refs/heads/branch-1 - ) && + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git tag -a annotated-tag-1 -m tag-1 && + git tag -a annotated-tag-2 -m tag-2 && + + branch_1_oid=$(git rev-parse branch-1) && + branch_2_oid=$(git rev-parse branch-2) && + tag_1_oid=$(git rev-parse annotated-tag-1) && + tag_2_oid=$(git rev-parse annotated-tag-2) && + tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) && + tag_2_peeled_oid=$(git rev-parse annotated-tag-2^{}) && + short_oid=$(printf "%s" $tag_1_peeled_oid | cut -c 1-4) && + + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + $short_oid refs/heads/branch-1 + ${branch_1_oid}x + $branch_2_oid refs/heads/bad-branch + $branch_2_oid refs/heads/branch. + $tag_1_oid refs/tags/annotated-tag-3 + ^$short_oid + $tag_2_oid refs/tags/annotated-tag-4. + ^$tag_2_peeled_oid garbage + EOF + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: packed-refs line 2: badPackedRefEntry: '\''$short_oid refs/heads/branch-1'\'' has invalid oid + error: packed-refs line 3: badPackedRefEntry: has no space after oid '\''$branch_1_oid'\'' but with '\''x'\'' + error: packed-refs line 4: badRefName: has bad refname '\'' refs/heads/bad-branch'\'' + error: packed-refs line 5: badRefName: has bad refname '\''refs/heads/branch.'\'' + error: packed-refs line 7: badPackedRefEntry: '\''$short_oid'\'' has invalid peeled oid + error: packed-refs line 8: badRefName: has bad refname '\''refs/tags/annotated-tag-4.'\'' + error: packed-refs line 9: badPackedRefEntry: has trailing garbage after peeled oid '\'' garbage'\'' + EOF + test_cmp expect err + ) +' + +test_expect_success 'packed-ref with sorted trait should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && ( - cd worktree-2 && - git update-ref refs/worktree/branch-4 refs/heads/branch-1 - ) && + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git tag -a annotated-tag-1 -m tag-1 && + branch_1_oid=$(git rev-parse branch-1) && + branch_2_oid=$(git rev-parse branch-2) && + tag_1_oid=$(git rev-parse annotated-tag-1) && + tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) && + refname1="refs/heads/main" && + refname2="refs/heads/foo" && + refname3="refs/tags/foo" && + + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + EOF + git refs verify 2>err && + rm .git/packed-refs && + test_must_be_empty err && - for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas" - do - printf "%s" $bad_content >$worktree1_refdir_prefix/bad-branch-1 && + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + $branch_2_oid $refname1 + EOF + git refs verify 2>err && + rm .git/packed-refs && + test_must_be_empty err && + + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + $branch_2_oid $refname1 + $branch_1_oid $refname2 + $tag_1_oid $refname3 + EOF test_must_fail git refs verify 2>err && cat >expect <<-EOF && - error: worktrees/worktree-1/refs/worktree/bad-branch-1: badRefContent: $bad_content + error: packed-refs line 3: packedRefUnsorted: refname '\''$refname2'\'' is less than previous refname '\''$refname1'\'' EOF - rm $worktree1_refdir_prefix/bad-branch-1 && - test_cmp expect err || return 1 - done && + rm .git/packed-refs && + test_cmp expect err && - for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas" - do - printf "%s" $bad_content >$worktree2_refdir_prefix/bad-branch-2 && + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + $tag_1_oid $refname3 + ^$tag_1_peeled_oid + $branch_2_oid $refname2 + EOF test_must_fail git refs verify 2>err && cat >expect <<-EOF && - error: worktrees/worktree-2/refs/worktree/bad-branch-2: badRefContent: $bad_content - EOF - rm $worktree2_refdir_prefix/bad-branch-2 && - test_cmp expect err || return 1 - done && - - printf "%s" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-no-newline && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/branch-no-newline: refMissingNewline: misses LF at the end - EOF - rm $worktree1_refdir_prefix/branch-no-newline && - test_cmp expect err && - - printf "%s garbage" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-garbage && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\'' - EOF - rm $worktree1_refdir_prefix/branch-garbage && - test_cmp expect err + error: packed-refs line 4: packedRefUnsorted: refname '\''$refname2'\'' is less than previous refname '\''$refname3'\'' + EOF + rm .git/packed-refs && + test_cmp expect err + ) +' + +test_expect_success 'packed-ref without sorted trait should not be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git tag -a annotated-tag-1 -m tag-1 && + branch_1_oid=$(git rev-parse branch-1) && + branch_2_oid=$(git rev-parse branch-2) && + tag_1_oid=$(git rev-parse annotated-tag-1) && + tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) && + refname1="refs/heads/main" && + refname2="refs/heads/foo" && + refname3="refs/tags/foo" && + + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled + $branch_2_oid $refname1 + $branch_1_oid $refname2 + EOF + git refs verify 2>err && + test_must_be_empty err + ) +' + +test_expect_success '--[no-]references option should apply to fsck' ' + test_when_finished "rm -rf repo" && + git init repo && + branch_dir_prefix=.git/refs/heads && + ( + cd repo && + test_commit default && + for trailing_content in " garbage" " more garbage" + do + printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage && + git fsck 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\'' + EOF + rm $branch_dir_prefix/branch-garbage && + test_cmp expect err || return 1 + done && + + for trailing_content in " garbage" " more garbage" + do + printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage && + git fsck --references 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\'' + EOF + rm $branch_dir_prefix/branch-garbage && + test_cmp expect err || return 1 + done && + + for trailing_content in " garbage" " more garbage" + do + printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage && + git fsck --no-references 2>err && + rm $branch_dir_prefix/branch-garbage && + test_must_be_empty err || return 1 + done + ) ' test_done diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh index 4618ffc108..002a75dee8 100755 --- a/t/t0610-reftable-basics.sh +++ b/t/t0610-reftable-basics.sh @@ -14,6 +14,13 @@ export GIT_TEST_DEFAULT_REF_FORMAT INVALID_OID=$(test_oid 001) +test_expect_success 'pack-refs does not crash with -h' ' + test_expect_code 129 git pack-refs -h >usage && + test_grep "[Uu]sage: git pack-refs " usage && + test_expect_code 129 nongit git pack-refs -h >usage && + test_grep "[Uu]sage: git pack-refs " usage +' + test_expect_success 'init: creates basic reftable structures' ' test_when_finished "rm -rf repo" && git init repo && diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh index ff9bf213aa..398865d6eb 100755 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@ -240,7 +240,8 @@ test_expect_success "setup" ' git config extensions.objectformat $test_hash_algo && git config extensions.compatobjectformat $test_compat_hash_algo && echo_without_newline "$hello_content" > hello && - git update-index --add hello + git update-index --add hello && + git commit -m "add hello file" ' run_blob_tests () { @@ -602,6 +603,34 @@ test_expect_success FUNNYNAMES '--batch-check, -Z with newline in input' ' test_cmp expect actual ' +test_expect_success 'setup with curly braches in input' ' + git branch "foo{bar" HEAD && + git branch "foo@" HEAD +' + +test_expect_success 'object reference with curly brace' ' + git cat-file -p "foo{bar:hello" >actual && + git cat-file -p HEAD:hello >expect && + test_cmp expect actual +' + +test_expect_success 'object reference with at-sign' ' + git cat-file -p "foo@@{0}:hello" >actual && + git cat-file -p HEAD:hello >expect && + test_cmp expect actual +' + +test_expect_success 'setup with commit with colon' ' + git commit-tree -m "testing: just a bunch of junk" HEAD^{tree} >out && + git branch other $(cat out) +' + +test_expect_success 'object reference via commit text search' ' + git cat-file -p "other^{/testing:}:hello" >actual && + git cat-file -p HEAD:hello >expect && + test_cmp expect actual +' + test_expect_success 'setup blobs which are likely to delta' ' test-tool genrandom foo 10240 >foo && { cat foo && echo plus; } >foo-plus && diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index e2316f1dd4..29045aad43 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -2068,4 +2068,13 @@ do done +test_expect_success 'update-ref should also create reflog for HEAD' ' + test_commit to-rewind && + git rev-parse HEAD >expect && + head=$(git symbolic-ref HEAD) && + git update-ref --create-reflog "$head" HEAD~ && + git rev-parse HEAD@{1} >actual && + test_cmp expect actual +' + test_done diff --git a/t/t1419-exclude-refs.sh b/t/t1419-exclude-refs.sh index c04eeb7211..04797aee59 100755 --- a/t/t1419-exclude-refs.sh +++ b/t/t1419-exclude-refs.sh @@ -46,6 +46,10 @@ test_expect_success 'setup' ' echo "create refs/heads/$name/$i $base" || return 1 done || return 1 done >in && + for i in 5 6 7 + do + echo "create refs/heads/bar/4/$i $base" || return 1 + done >>in && echo "delete refs/heads/main" >>in && git update-ref --stdin <in && @@ -99,9 +103,17 @@ test_expect_success 'adjacent, non-overlapping excluded regions' ' esac ' -test_expect_success 'overlapping excluded regions' ' +test_expect_success 'non-directory excluded regions' ' for_each_ref__exclude refs/heads refs/heads/ba refs/heads/baz >actual 2>perf && - for_each_ref refs/heads/foo refs/heads/quux >expect && + for_each_ref refs/heads/bar refs/heads/foo refs/heads/quux >expect && + + test_cmp expect actual && + assert_jumps 1 perf +' + +test_expect_success 'overlapping excluded regions' ' + for_each_ref__exclude refs/heads refs/heads/bar refs/heads/bar/4 >actual 2>perf && + for_each_ref refs/heads/baz refs/heads/foo refs/heads/quux >expect && test_cmp expect actual && assert_jumps 1 perf @@ -155,4 +167,14 @@ test_expect_success 'meta-characters are discarded' ' assert_no_jumps perf ' +test_expect_success 'empty string exclude pattern is ignored' ' + git update-ref refs/heads/loose $(git rev-parse refs/heads/foo/1) && + + for_each_ref__exclude refs/heads "" >actual 2>perf && + for_each_ref >expect && + + test_cmp expect actual && + assert_no_jumps perf +' + test_done diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh index f59bc4860f..2ab97e1b7d 100755 --- a/t/t1460-refs-migrate.sh +++ b/t/t1460-refs-migrate.sh @@ -9,14 +9,21 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME # Migrate the provided repository from one format to the other and # verify that the references and logs are migrated over correctly. -# Usage: test_migration <repo> <format> <skip_reflog_verify> +# Usage: test_migration <repo> <format> [<skip_reflog_verify> [<options...>]] # <repo> is the relative path to the repo to be migrated. # <format> is the ref format to be migrated to. -# <skip_reflog_verify> (true or false) whether to skip reflog verification. +# <skip_reflog_verify> (default: false) whether to skip reflog verification. +# <options...> are other options be passed directly to 'git refs migrate'. test_migration () { repo=$1 && format=$2 && - skip_reflog_verify=${3:-false} && + shift 2 && + skip_reflog_verify=false && + if test $# -ge 1 + then + skip_reflog_verify=$1 + shift + fi && git -C "$repo" for-each-ref --include-root-refs \ --format='%(refname) %(objectname) %(symref)' >expect && if ! $skip_reflog_verify @@ -25,7 +32,7 @@ test_migration () { git -C "$repo" reflog list >expect_log_list fi && - git -C "$repo" refs migrate --ref-format="$2" && + git -C "$repo" refs migrate --ref-format="$format" "$@" && git -C "$repo" for-each-ref --include-root-refs \ --format='%(refname) %(objectname) %(symref)' >actual && @@ -224,9 +231,51 @@ do test_commit --date "100003000 +0700" --no-tag -C repo second && test_migration repo "$to_format" ' + + test_expect_success "$from_format -> $to_format: stash is retained" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + ( + cd repo && + test_commit initial A && + echo foo >A && + git stash push && + echo bar >A && + git stash push && + git stash list >expect.reflog && + test_migration . "$to_format" && + git stash list >actual.reflog && + test_cmp expect.reflog actual.reflog + ) + ' + + test_expect_success "$from_format -> $to_format: skip reflog with --skip-reflog" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + # we see that the repository contains reflogs. + git -C repo reflog --all >reflogs && + test_line_count = 2 reflogs && + test_migration repo "$to_format" true --no-reflog && + # there should be no reflogs post migration. + git -C repo reflog --all >reflogs && + test_must_be_empty reflogs + ' done done +test_expect_success 'multiple reftable blocks with multiple entries' ' + test_when_finished "rm -rf repo" && + git init --ref-format=files repo && + test_commit -C repo first && + printf "create refs/heads/ref-%d HEAD\n" $(test_seq 5000) >stdin && + git -C repo update-ref --stdin <stdin && + test_commit -C repo second && + printf "update refs/heads/ref-%d HEAD\n" $(test_seq 3000) >stdin && + git -C repo update-ref --stdin <stdin && + test_migration repo reftable +' + test_expect_success 'migrating from files format deletes backend files' ' test_when_finished "rm -rf repo" && git init --ref-format=files repo && diff --git a/t/t2006-checkout-index-basic.sh b/t/t2006-checkout-index-basic.sh index bac231b167..fedd2cc097 100755 --- a/t/t2006-checkout-index-basic.sh +++ b/t/t2006-checkout-index-basic.sh @@ -21,6 +21,13 @@ test_expect_success 'checkout-index -h in broken repository' ' test_grep "[Uu]sage" broken/usage ' +test_expect_success 'checkout-index does not crash with -h' ' + test_expect_code 129 git checkout-index -h >usage && + test_grep "[Uu]sage: git checkout-index " usage && + test_expect_code 129 nongit git checkout-index -h >usage && + test_grep "[Uu]sage: git checkout-index " usage +' + test_expect_success 'checkout-index reports errors (cmdline)' ' test_must_fail git checkout-index -- does-not-exist 2>stderr && test_grep not.in.the.cache stderr diff --git a/t/t3004-ls-files-basic.sh b/t/t3004-ls-files-basic.sh index a1078f8701..4034a5a59f 100755 --- a/t/t3004-ls-files-basic.sh +++ b/t/t3004-ls-files-basic.sh @@ -34,6 +34,13 @@ test_expect_success 'ls-files -h in corrupt repository' ' test_grep "[Uu]sage: git ls-files " broken/usage ' +test_expect_success 'ls-files does not crash with -h' ' + test_expect_code 129 git ls-files -h >usage && + test_grep "[Uu]sage: git ls-files " usage && + test_expect_code 129 nongit git ls-files -h >usage && + test_grep "[Uu]sage: git ls-files " usage +' + test_expect_success SYMLINKS 'ls-files with absolute paths to symlinks' ' mkdir subs && ln -s nosuch link && diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index a3a21c54cf..f3e720dc10 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -410,6 +410,20 @@ test_expect_success 'bare main worktree has HEAD at branch deleted by secondary git -C secondary branch -D main ' +test_expect_success 'secondary worktrees recognize core.bare=true in main config.worktree' ' + test_when_finished "rm -rf bare_repo non_bare_repo secondary_worktree" && + git init -b main non_bare_repo && + test_commit -C non_bare_repo x && + + git clone --bare non_bare_repo bare_repo && + git -C bare_repo config extensions.worktreeConfig true && + git -C bare_repo config unset core.bare && + git -C bare_repo config --worktree core.bare true && + + git -C bare_repo worktree add ../secondary_worktree && + git -C secondary_worktree checkout main +' + test_expect_success 'git branch --list -v with --abbrev' ' test_when_finished "git branch -D t" && git branch t && diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index 500c9d0e72..a6bd88a58d 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -368,6 +368,34 @@ test_expect_success 'git branch --format with ahead-behind' ' test_cmp expect actual ' +test_expect_success 'git branch `--sort=[-]ahead-behind` option' ' + cat >expect <<-\EOF && + (HEAD detached from fromtag) 0 0 + refs/heads/ambiguous 0 0 + refs/heads/branch-two 0 0 + refs/heads/branch-one 1 0 + refs/heads/main 1 0 + refs/heads/ref-to-branch 1 0 + refs/heads/ref-to-remote 1 0 + EOF + git branch --format="%(refname) %(ahead-behind:HEAD)" \ + --sort=refname --sort=ahead-behind:HEAD >actual && + test_cmp expect actual && + + cat >expect <<-\EOF && + (HEAD detached from fromtag) 0 0 + refs/heads/branch-one 1 0 + refs/heads/main 1 0 + refs/heads/ref-to-branch 1 0 + refs/heads/ref-to-remote 1 0 + refs/heads/ambiguous 0 0 + refs/heads/branch-two 0 0 + EOF + git branch --format="%(refname) %(ahead-behind:HEAD)" \ + --sort=refname --sort=-ahead-behind:HEAD >actual && + test_cmp expect actual +' + test_expect_success 'git branch with --format=%(rest) must fail' ' test_must_fail git branch --format="%(rest)" >actual ' diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index ecfc02062c..2aee9789a2 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -791,6 +791,20 @@ test_expect_success 'reword' ' grep "C changed" actual ' +test_expect_success 'reword fast-forwarded empty commit' ' + git commit --allow-empty -m "empty commit" --only && + ( + set_fake_editor && + FAKE_COMMIT_AMEND=edited FAKE_LINES="reword 1" \ + git rebase -i HEAD^ + ) && + test_commit_message HEAD <<-\EOF + empty commit + + edited + EOF +' + test_expect_success 'no uncommitted changes when rewording and the todo list is reloaded' ' git checkout E && test_when_finished "git checkout @{-1}" && diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh index 2593711fec..b84d68c4b9 100755 --- a/t/t3430-rebase-merges.sh +++ b/t/t3430-rebase-merges.sh @@ -610,4 +610,24 @@ test_expect_success 'truncate label names' ' grep "label 0123456789-$" out ' +test_expect_success 'reword fast-forwarded empty merge commit' ' + oid="$(git commit-tree -m "D1" -p A D^{tree})" && + oid="$(git commit-tree -m "empty merge" -p D -p $oid D^{tree})" && + + write_script sequence-editor.sh <<-\EOF && + sed /^merge/s/-C/-c/ "$1" >"$1.tmp" + mv "$1.tmp" "$1" + EOF + + ( + test_set_sequence_editor "$(pwd)/sequence-editor.sh" && + GIT_EDITOR="echo edited >>" git rebase -i -r D $oid + ) && + test_commit_message HEAD <<-\EOF + empty merge + + edited + EOF +' + test_done diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh index 389670262e..58b3759935 100755 --- a/t/t3650-replay-basics.sh +++ b/t/t3650-replay-basics.sh @@ -195,4 +195,26 @@ test_expect_success 'using replay on bare repo to rebase multiple divergent bran done ' +test_expect_success 'merge.directoryRenames=false' ' + # create a test case that stress-tests the rename caching + git switch -c rename-onto && + + mkdir -p to-rename && + test_commit to-rename/move && + + mkdir -p renamed-directory && + git mv to-rename/move* renamed-directory/ && + test_tick && + git commit -m renamed-directory && + + git switch -c rename-from HEAD^ && + test_commit to-rename/add-a-file && + echo modified >to-rename/add-a-file.t && + test_tick && + git commit -m modified to-rename/add-a-file.t && + + git -c merge.directoryRenames=false replay \ + --onto rename-onto rename-onto..rename-from +' + test_done diff --git a/t/t4070-diff-pairs.sh b/t/t4070-diff-pairs.sh new file mode 100755 index 0000000000..70deafb860 --- /dev/null +++ b/t/t4070-diff-pairs.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +test_description='basic diff-pairs tests' +. ./test-lib.sh + +# This creates a diff with added, modified, deleted, renamed, copied, and +# typechange entries. This includes a submodule to test submodule diff support. +test_expect_success 'setup' ' + test_config_global protocol.file.allow always && + git init sub && + test_commit -C sub initial && + + git init main && + cd main && + echo to-be-gone >deleted && + echo original >modified && + echo now-a-file >symlink && + test_seq 200 >two-hundred && + test_seq 201 500 >five-hundred && + git add . && + test_tick && + git commit -m base && + git tag base && + + git submodule add ../sub && + echo now-here >added && + echo new >modified && + rm deleted && + mkdir subdir && + echo content >subdir/file && + mv two-hundred renamed && + test_seq 201 500 | sed s/300/modified/ >copied && + rm symlink && + git add -A . && + test_ln_s_add dest symlink && + test_tick && + git commit -m new && + git tag new +' + +test_expect_success 'diff-pairs recreates --raw' ' + git diff-tree -r -M -C -C -z base new >expect && + git diff-pairs --raw -z >actual <expect && + test_cmp expect actual +' + +test_expect_success 'diff-pairs can create -p output' ' + git diff-tree -p -M -C -C base new >expect && + git diff-tree -r -M -C -C -z base new | + git diff-pairs -p -z >actual && + test_cmp expect actual +' + +test_expect_success 'diff-pairs does not support normal raw diff input' ' + git diff-tree -r base new | + test_must_fail git diff-pairs >out 2>err && + + echo "usage: working without -z is not supported" >expect && + test_must_be_empty out && + test_cmp expect err +' + +test_expect_success 'diff-pairs does not support tree objects as input' ' + git diff-tree -z base new | + test_must_fail git diff-pairs -z >out 2>err && + + echo "fatal: tree objects not supported" >expect && + test_must_be_empty out && + test_cmp expect err +' + +test_expect_success 'diff-pairs does not support pathspec arguments' ' + git diff-tree -r -z base new | + test_must_fail git diff-pairs -z -- new >out 2>err && + + echo "usage: pathspec arguments not supported" >expect && + test_must_be_empty out && + test_cmp expect err +' + +test_expect_success 'diff-pairs explicit queue flush' ' + git diff-tree -r -M -C -C -z base new >expect && + printf "\0" >>expect && + git diff-tree -r -M -C -C -z base new >>expect && + + git diff-pairs --raw -z <expect >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh index 146e73d8f5..a5664f3eb3 100755 --- a/t/t4100-apply-stat.sh +++ b/t/t4100-apply-stat.sh @@ -38,4 +38,17 @@ incomplete (1) incomplete (2) EOF +test_expect_success 'applying a hunk header which overflows fails' ' + cat >patch <<-\EOF && + diff -u a/file b/file + --- a/file + +++ b/file + @@ -98765432109876543210 +98765432109876543210 @@ + -a + +b + EOF + test_must_fail git apply patch 2>err && + echo "error: corrupt patch at line 4" >expect && + test_cmp expect err +' test_done diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh index edb38da701..8e1ecf8a68 100755 --- a/t/t4151-am-abort.sh +++ b/t/t4151-am-abort.sh @@ -112,7 +112,7 @@ test_expect_success 'am --abort will keep dirty index intact' ' test_expect_success 'am -3 stops on conflict on unborn branch' ' git checkout -f --orphan orphan && git reset && - rm -f otherfile-4 && + rm -f file-1 otherfile-4 && test_must_fail git am -3 0003-*.patch && test 2 -eq $(git ls-files -u | wc -l) && test 4 = "$(cat otherfile-4)" diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 2421491931..4a6242ff99 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -113,6 +113,18 @@ test_expect_success 'check-mailmap --stdin simple address: no mapping' ' test_cmp expect actual ' +test_expect_success 'check-mailmap name and address: mapping' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-EOF && + Bug Reports <bugs-new@company.xx> Bugs <bugs@company.xx> + EOF + cat >expect <<-EOF && + <bugs@company.xx> + EOF + git check-mailmap "bugs@company.xx" >actual && + test_cmp expect actual +' + test_expect_success 'No mailmap' ' cat >expect <<-EOF && $GIT_AUTHOR_NAME (1): diff --git a/t/t4206-log-follow-harder-copies.sh b/t/t4206-log-follow-harder-copies.sh index bcab71c8e8..190c484321 100755 --- a/t/t4206-log-follow-harder-copies.sh +++ b/t/t4206-log-follow-harder-copies.sh @@ -54,4 +54,36 @@ test_expect_success 'validate the output.' ' compare_diff_patch current expected ' +test_expect_success 'log --follow -B does not BUG' ' + git switch --orphan break_and_follow_are_icky_so_use_both && + + test_seq 1 127 >numbers && + git add numbers && + git commit -m "numbers" && + + printf "%s\n" A B C D E F G H I J K L M N O Q R S T U V W X Y Z >pool && + echo changed >numbers && + git add pool numbers && + git commit -m "pool" && + + git log -1 -B --raw --follow -- "p*" +' + +test_expect_success 'log --follow -B does not die or use uninitialized memory' ' + printf "%s\n" A B C D E F G H I J K L M N O P Q R S T U V W X Y Z >z && + git add z && + git commit -m "Initial" && + + test_seq 1 130 >z && + echo lame >somefile && + git add z somefile && + git commit -m "Rewrite z, introduce lame somefile" && + + echo Content >somefile && + git add somefile && + git commit -m "Rewrite somefile" && + + git log -B --follow somefile +' + test_done diff --git a/t/t4209-log-pickaxe.sh b/t/t4209-log-pickaxe.sh index a675ace081..0e2f80a268 100755 --- a/t/t4209-log-pickaxe.sh +++ b/t/t4209-log-pickaxe.sh @@ -93,6 +93,22 @@ test_expect_success 'usage: --no-pickaxe-regex' ' test_cmp expect actual ' +test_expect_success 'usage: -G and -S with empty argument' ' + cat >expect <<-\EOF && + error: -S requires a non-empty argument + EOF + + test_expect_code 129 git log -S "" 2>actual && + test_cmp expect actual && + + cat >expect <<-\EOF && + error: -G requires a non-empty argument + EOF + + test_expect_code 129 git log -G "" 2>actual && + test_cmp expect actual +' + test_log expect_initial --grep initial test_log expect_nomatch --grep InItial test_log_icase expect_initial --grep InItial diff --git a/t/t4255-am-submodule.sh b/t/t4255-am-submodule.sh index a7ba08f728..e6679a01b4 100755 --- a/t/t4255-am-submodule.sh +++ b/t/t4255-am-submodule.sh @@ -19,7 +19,6 @@ am_3way () { $2 git am --3way patch } -KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 test_submodule_switch_func "am_3way" test_expect_success 'setup diff.submodule' ' diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh index eea19907b5..44f7d07759 100755 --- a/t/t4301-merge-tree-write-tree.sh +++ b/t/t4301-merge-tree-write-tree.sh @@ -73,6 +73,12 @@ test_expect_success 'Clean merge' ' test_cmp expect actual ' +# Repeat the previous test, but turn off rename detection +test_expect_success 'Failed merge without rename detection' ' + test_must_fail git -c diff.renames=false merge-tree --write-tree side1 side3 >out && + grep "CONFLICT (modify/delete): numbers deleted" out +' + test_expect_success 'Content merge and a few conflicts' ' git checkout side1^0 && test_must_fail git merge side2 && diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index d1d6248558..5ac8d39094 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -689,4 +689,38 @@ do ' done +test_expect_success 'valid and invalid --name-hash-versions' ' + sane_unset GIT_TEST_NAME_HASH_VERSION && + + # Valid values are hard to verify other than "do not fail". + # Performance tests will be more valuable to validate these versions. + # Negative values are converted to version 1. + for value in -1 1 2 + do + git pack-objects base --all --name-hash-version=$value || return 1 + done && + + # Invalid values have clear post-conditions. + for value in 0 3 + do + test_must_fail git pack-objects base --all --name-hash-version=$value 2>err && + test_grep "invalid --name-hash-version option" err || return 1 + done +' + +# The following test is not necessarily a permanent choice, but since we do not +# have a "name hash version" bit in the .bitmap file format, we cannot write the +# hash values into the .bitmap file without risking breakage later. +# +# TODO: Make these compatible in the future and replace this test with the +# expected behavior when both are specified. +test_expect_success '--name-hash-version=2 and --write-bitmap-index are incompatible' ' + git pack-objects base --all --name-hash-version=2 --write-bitmap-index 2>err && + test_grep "currently, --write-bitmap-index requires --name-hash-version=1" err && + + # --stdout option silently removes --write-bitmap-index + git pack-objects --stdout --all --name-hash-version=2 --write-bitmap-index >out 2>err && + ! test_grep "currently, --write-bitmap-index requires --name-hash-version=1" err +' + test_done diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh index eabfcd7ff6..621bbbdd26 100755 --- a/t/t5310-pack-bitmaps.sh +++ b/t/t5310-pack-bitmaps.sh @@ -26,6 +26,36 @@ has_any () { grep -Ff "$1" "$2" } +# Since name-hash values are stored in the .bitmap files, add a test +# that checks that the name-hash calculations are stable across versions. +# Not exhaustive, but these hashing algorithms would be hard to change +# without causing deviations here. +test_expect_success 'name-hash value stability' ' + cat >names <<-\EOF && + first + second + third + a/one-long-enough-for-collisions + b/two-long-enough-for-collisions + many/parts/to/this/path/enough/to/collide/in/v2 + enough/parts/to/this/path/enough/to/collide/in/v2 + EOF + + test-tool name-hash <names >out && + + cat >expect <<-\EOF && + 2582249472 1763573760 first + 2289942528 1188134912 second + 2300837888 1130758144 third + 2544516325 3963087891 a/one-long-enough-for-collisions + 2544516325 4013419539 b/two-long-enough-for-collisions + 1420111091 1709547268 many/parts/to/this/path/enough/to/collide/in/v2 + 1420111091 1709547268 enough/parts/to/this/path/enough/to/collide/in/v2 + EOF + + test_cmp expect out +' + test_bitmap_cases () { writeLookupTable=false for i in "$@" @@ -419,7 +449,10 @@ test_bitmap_cases () { cat >expect <<-\EOF && error: missing value for '\''pack.preferbitmaptips'\'' EOF - git repack -adb 2>actual && + + # Disable name hash version adjustment due to stderr comparison. + GIT_TEST_NAME_HASH_VERSION=1 \ + git repack -adb 2>actual && test_cmp expect actual ) ' diff --git a/t/t5323-pack-redundant.sh b/t/t5323-pack-redundant.sh index 8dbbcc5e51..688cd9706c 100755 --- a/t/t5323-pack-redundant.sh +++ b/t/t5323-pack-redundant.sh @@ -36,6 +36,12 @@ relationship between packs and objects is as follows: . ./test-lib.sh +if ! test_have_prereq WITHOUT_BREAKING_CHANGES +then + skip_all='skipping git-pack-redundant tests; built with breaking changes' + test_done +fi + main_repo=main.git shared_repo=shared.git diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh index 1dd6284756..3905cb6e4f 100755 --- a/t/t5333-pseudo-merge-bitmaps.sh +++ b/t/t5333-pseudo-merge-bitmaps.sh @@ -208,7 +208,8 @@ test_expect_success 'bitmapPseudoMerge.stableThreshold creates stable groups' ' ' test_expect_success 'out of order thresholds are rejected' ' - test_must_fail git \ + # Disable the test var to remove a stderr message. + test_must_fail env GIT_TEST_NAME_HASH_VERSION=1 git \ -c bitmapPseudoMerge.test.pattern="refs/*" \ -c bitmapPseudoMerge.test.threshold=1.month.ago \ -c bitmapPseudoMerge.test.stableThreshold=1.week.ago \ diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index 3f81f16e13..8f018d2f23 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -55,6 +55,13 @@ test_expect_success setup ' echo Rebase && git log' +test_expect_success 'send-pack does not crash with -h' ' + test_expect_code 129 git send-pack -h >usage && + test_grep "[Uu]sage: git send-pack " usage && + test_expect_code 129 nongit git send-pack -h >usage && + test_grep "[Uu]sage: git send-pack " usage +' + test_expect_success 'pack the source repository' ' git repack -a -d && git prune diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh index 723d1e17ec..17a46fd3ba 100755 --- a/t/t5401-update-hooks.sh +++ b/t/t5401-update-hooks.sh @@ -64,14 +64,14 @@ test_expect_success 'updated as expected' ' ' test_expect_success 'hooks ran' ' - test -f victim.git/pre-receive.args && - test -f victim.git/pre-receive.stdin && - test -f victim.git/update.args && - test -f victim.git/update.stdin && - test -f victim.git/post-receive.args && - test -f victim.git/post-receive.stdin && - test -f victim.git/post-update.args && - test -f victim.git/post-update.stdin + test_path_is_file victim.git/pre-receive.args && + test_path_is_file victim.git/pre-receive.stdin && + test_path_is_file victim.git/update.args && + test_path_is_file victim.git/update.stdin && + test_path_is_file victim.git/post-receive.args && + test_path_is_file victim.git/post-receive.stdin && + test_path_is_file victim.git/post-update.args && + test_path_is_file victim.git/post-update.stdin ' test_expect_success 'pre-receive hook input' ' diff --git a/t/t5503-tagfollow.sh b/t/t5503-tagfollow.sh index 195fc64dd4..845ca43ea0 100755 --- a/t/t5503-tagfollow.sh +++ b/t/t5503-tagfollow.sh @@ -160,4 +160,18 @@ test_expect_success 'new clone fetch main and tags' ' test_cmp expect actual ' +test_expect_success 'fetch specific OID with tag following' ' + git init --bare clone3.git && + ( + cd clone3.git && + git remote add origin .. && + git fetch origin $B:refs/heads/main && + + git -C .. for-each-ref >expect && + git for-each-ref >actual && + + test_cmp expect actual + ) +' + test_done diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index 8212a70be8..58074506c5 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -64,12 +64,6 @@ test_expect_success 'fetch with transfer.fsckobjects' ' ) ' -cat >exp <<EOF -To dst -! refs/heads/main:refs/heads/test [remote rejected] (missing necessary objects) -Done -EOF - test_expect_success 'push without strict' ' rm -rf dst && git init dst && @@ -78,6 +72,11 @@ test_expect_success 'push without strict' ' git config fetch.fsckobjects false && git config transfer.fsckobjects false ) && + cat >exp <<-\EOF && + To dst + ! refs/heads/main:refs/heads/test [remote rejected] (missing necessary objects) + Done + EOF test_must_fail git push --porcelain dst main:refs/heads/test >act && test_cmp exp act ' @@ -94,11 +93,6 @@ test_expect_success 'push with !receive.fsckobjects' ' test_cmp exp act ' -cat >exp <<EOF -To dst -! refs/heads/main:refs/heads/test [remote rejected] (unpacker error) -EOF - test_expect_success 'push with receive.fsckobjects' ' rm -rf dst && git init dst && @@ -107,6 +101,10 @@ test_expect_success 'push with receive.fsckobjects' ' git config receive.fsckobjects true && git config transfer.fsckobjects false ) && + cat >exp <<-\EOF && + To dst + ! refs/heads/main:refs/heads/test [remote rejected] (unpacker error) + EOF test_must_fail git push --porcelain dst main:refs/heads/test >act && test_cmp exp act ' @@ -129,15 +127,14 @@ test_expect_success 'repair the "corrupt or missing" object' ' git fsck ' -cat >bogus-commit <<EOF -tree $EMPTY_TREE -author Bugs Bunny 1234567890 +0000 -committer Bugs Bunny <bugs@bun.ni> 1234567890 +0000 - -This commit object intentionally broken -EOF - test_expect_success 'setup bogus commit' ' + cat >bogus-commit <<-EOF && + tree $EMPTY_TREE + author Bugs Bunny 1234567890 +0000 + committer Bugs Bunny <bugs@bun.ni> 1234567890 +0000 + + This commit object intentionally broken + EOF commit="$(git hash-object --literally -t commit -w --stdin <bogus-commit)" ' @@ -167,6 +164,8 @@ test_expect_success 'fsck with unsorted skipList' ' test_expect_success 'fsck with invalid or bogus skipList input' ' git -c fsck.skipList=/dev/null -c fsck.missingEmail=ignore fsck && + test_must_fail git -c fsck.skipList -c fsck.missingEmail=ignore fsck 2>err && + test_grep "unable to parse '\'fsck.skiplist\'' from command-line config" err && test_must_fail git -c fsck.skipList=does-not-exist -c fsck.missingEmail=ignore fsck 2>err && test_grep "could not open.*: does-not-exist" err && test_must_fail git -c fsck.skipList=.git/config -c fsck.missingEmail=ignore fsck 2>err && @@ -213,6 +212,11 @@ test_expect_success 'fsck with exhaustive accepted skipList input (various types test_must_be_empty err ' +test_expect_success 'receive-pack with missing receive.fsck.skipList path' ' + test_must_fail git -c receive.fsck.skipList receive-pack dst 2>err && + test_grep "unable to parse '\'receive.fsck.skiplist\'' from command-line config" err +' + test_expect_success 'push with receive.fsck.skipList' ' git push . $commit:refs/heads/bogus && rm -rf dst && @@ -255,6 +259,9 @@ test_expect_success 'fetch with fetch.fsck.skipList' ' test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && # Invalid and/or bogus skipList input + test_must_fail git --git-dir=dst/.git -c fetch.fsck.skipList fetch \ + "file://$(pwd)" $refspec 2>err && + test_grep "unable to parse '\'fetch.fsck.skiplist\'' from command-line config" err && git --git-dir=dst/.git config fetch.fsck.skipList /dev/null && test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && git --git-dir=dst/.git config fetch.fsck.skipList does-not-exist && diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index 519f7973e3..bb7e0c6879 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -589,6 +589,16 @@ test_expect_success 'add --mirror setting HEAD' ' ) ' +test_expect_success 'non-mirror fetch does not interfere with mirror' ' + test_when_finished rm -rf headnotmain && + ( + git init --bare -b notmain headnotmain && + cd headnotmain && + git remote add -f other ../two && + test "$(git symbolic-ref HEAD)" = "refs/heads/notmain" + ) +' + test_expect_success 'add --mirror=fetch' ' mkdir mirror-fetch && git init -b main mirror-fetch/parent && @@ -1113,7 +1123,7 @@ Pull: refs/heads/main:refs/heads/origin Pull: refs/heads/next:refs/heads/origin2 EOF -test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' ' +test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/remotes' ' git clone one five && origin_url=$(pwd)/one && ( @@ -1139,7 +1149,7 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' ' ) ' -test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' ' +test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches' ' git clone --template= one six && origin_url=$(pwd)/one && ( @@ -1155,7 +1165,7 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' ' ) ' -test_expect_success 'migrate a remote from named file in $GIT_DIR/branches (2)' ' +test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches (2)' ' git clone --template= one seven && ( cd seven && diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 2d9587059f..5f350facf5 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -34,14 +34,11 @@ test_expect_success "clone and setup child repos" ' git clone . three && ( cd three && - git config branch.main.remote two && - git config branch.main.merge refs/heads/one && - mkdir -p .git/remotes && - cat >.git/remotes/two <<-\EOF - URL: ../two/.git/ - Pull: refs/heads/main:refs/heads/two - Pull: refs/heads/one:refs/heads/one - EOF + git config set remote.two.url ../two/.git/ && + git config set remote.two.fetch refs/heads/main:refs/heads/two && + git config set --append remote.two.fetch refs/heads/one:refs/heads/one && + git config set branch.main.remote two && + git config set branch.main.merge refs/heads/one ) && git clone . bundle && git clone . seven @@ -84,6 +81,23 @@ test_expect_success "fetch test remote HEAD" ' branch=$(git rev-parse refs/remotes/origin/main) && test "z$head" = "z$branch"' +test_expect_success "fetch test remote HEAD in bare repository" ' + test_when_finished rm -rf barerepo && + ( + cd "$D" && + git init --bare barerepo && + cd barerepo && + git remote add upstream ../two && + git fetch upstream && + git rev-parse --verify refs/remotes/upstream/HEAD && + git rev-parse --verify refs/remotes/upstream/main && + head=$(git rev-parse refs/remotes/upstream/HEAD) && + branch=$(git rev-parse refs/remotes/upstream/main) && + test "z$head" = "z$branch" + ) +' + + test_expect_success "fetch test remote HEAD change" ' cd "$D" && cd two && @@ -1240,7 +1254,12 @@ test_expect_success 'all boundary commits are excluded' ' test_tick && git merge otherside && ad=$(git log --no-walk --format=%ad HEAD) && - git bundle create twoside-boundary.bdl main --since="$ad" && + + # If the a different name hash function is used here, then no delta + # pair is found and the bundle does not expand to three objects + # when fixing the thin object. + GIT_TEST_NAME_HASH_VERSION=1 \ + git bundle create twoside-boundary.bdl main --since="$ad" && test_bundle_object_count --thin twoside-boundary.bdl 3 ' diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh index 320d26796d..4e6026c611 100755 --- a/t/t5515-fetch-merge-logic.sh +++ b/t/t5515-fetch-merge-logic.sh @@ -104,28 +104,31 @@ test_expect_success setup ' git config remote.config-glob.fetch refs/heads/*:refs/remotes/rem/* && remotes="$remotes config-glob" && - mkdir -p .git/remotes && - cat >.git/remotes/remote-explicit <<-\EOF && - URL: ../.git/ - Pull: refs/heads/main:remotes/rem/main - Pull: refs/heads/one:remotes/rem/one - Pull: two:remotes/rem/two - Pull: refs/heads/three:remotes/rem/three - EOF - remotes="$remotes remote-explicit" && - - cat >.git/remotes/remote-glob <<-\EOF && - URL: ../.git/ - Pull: refs/heads/*:refs/remotes/rem/* - EOF - remotes="$remotes remote-glob" && - - mkdir -p .git/branches && - echo "../.git" > .git/branches/branches-default && - remotes="$remotes branches-default" && - - echo "../.git#one" > .git/branches/branches-one && - remotes="$remotes branches-one" && + if test_have_prereq WITHOUT_BREAKING_CHANGES + then + mkdir -p .git/remotes && + cat >.git/remotes/remote-explicit <<-\EOF && + URL: ../.git/ + Pull: refs/heads/main:remotes/rem/main + Pull: refs/heads/one:remotes/rem/one + Pull: two:remotes/rem/two + Pull: refs/heads/three:remotes/rem/three + EOF + remotes="$remotes remote-explicit" && + + cat >.git/remotes/remote-glob <<-\EOF && + URL: ../.git/ + Pull: refs/heads/*:refs/remotes/rem/* + EOF + remotes="$remotes remote-glob" && + + mkdir -p .git/branches && + echo "../.git" > .git/branches/branches-default && + remotes="$remotes branches-default" && + + echo "../.git#one" > .git/branches/branches-one && + remotes="$remotes branches-one" + fi && for remote in $remotes ; do git config branch.br-$remote.remote $remote && diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 041d7d806f..2904399e97 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -495,7 +495,7 @@ test_expect_success 'push tag with non-existent, incomplete dest' ' ' -test_expect_success 'push sha1 with non-existent, incomplete dest' ' +test_expect_success 'push oid with non-existent, incomplete dest' ' mk_test testrepo && test_must_fail git push testrepo $(git rev-parse main):foo @@ -975,7 +975,7 @@ test_expect_success 'allow push to HEAD of non-bare repository (config)' ' ! grep "warning: updating the current branch" stderr ' -test_expect_success 'fetch with branches' ' +test_expect_success WITHOUT_BREAKING_CHANGES 'fetch with branches' ' mk_empty testrepo && git branch second $the_first_commit && git checkout second && @@ -991,7 +991,7 @@ test_expect_success 'fetch with branches' ' git checkout main ' -test_expect_success 'fetch with branches containing #' ' +test_expect_success WITHOUT_BREAKING_CHANGES 'fetch with branches containing #' ' mk_empty testrepo && mkdir testrepo/.git/branches && echo "..#second" > testrepo/.git/branches/branch2 && @@ -1005,7 +1005,7 @@ test_expect_success 'fetch with branches containing #' ' git checkout main ' -test_expect_success 'push with branches' ' +test_expect_success WITHOUT_BREAKING_CHANGES 'push with branches' ' mk_empty testrepo && git checkout second && @@ -1022,7 +1022,7 @@ test_expect_success 'push with branches' ' ) ' -test_expect_success 'push with branches containing #' ' +test_expect_success WITHOUT_BREAKING_CHANGES 'push with branches containing #' ' mk_empty testrepo && test_when_finished "rm -rf .git/branches" && @@ -1211,18 +1211,16 @@ test_expect_success 'push --porcelain --dry-run rejected' ' ' test_expect_success 'push --prune' ' - mk_test testrepo heads/main heads/second heads/foo heads/bar && + mk_test testrepo heads/main heads/foo heads/bar && git push --prune testrepo : && check_push_result testrepo $the_commit heads/main && - check_push_result testrepo $the_first_commit heads/second && ! check_push_result testrepo $the_first_commit heads/foo heads/bar ' test_expect_success 'push --prune refspec' ' - mk_test testrepo tmp/main tmp/second tmp/foo tmp/bar && + mk_test testrepo tmp/main tmp/foo tmp/bar && git push --prune testrepo "refs/heads/*:refs/tmp/*" && check_push_result testrepo $the_commit tmp/main && - check_push_result testrepo $the_first_commit tmp/second && ! check_push_result testrepo $the_first_commit tmp/foo tmp/bar ' @@ -1253,7 +1251,7 @@ do ' done -test_expect_success 'fetch exact SHA1' ' +test_expect_success 'fetch exact oid' ' mk_test testrepo heads/main hidden/one && git push testrepo main:refs/hidden/one && ( @@ -1299,7 +1297,7 @@ test_expect_success 'fetch exact SHA1' ' ) ' -test_expect_success 'fetch exact SHA1 in protocol v2' ' +test_expect_success 'fetch exact oid in protocol v2' ' mk_test testrepo heads/main hidden/one && git push testrepo main:refs/hidden/one && git -C testrepo config transfer.hiderefs refs/hidden && @@ -1314,8 +1312,10 @@ test_expect_success 'fetch exact SHA1 in protocol v2' ' test_must_fail git -C child cat-file -t $the_commit && # fetching the hidden object succeeds by default - # NEEDSWORK: should this match the v0 behavior instead? - git -C child fetch -v ../testrepo $the_commit:refs/heads/copy + GIT_TRACE_PACKET=$PWD/trace.out \ + git -C child fetch -v ../testrepo $the_commit:refs/heads/copy && + + test_grep ! "ref-prefix.*$the_commit" trace.out ' for configallowtipsha1inwant in true false diff --git a/t/t5540-http-push-webdav.sh b/t/t5540-http-push-webdav.sh index 37db3dec0c..3fa05ff185 100755 --- a/t/t5540-http-push-webdav.sh +++ b/t/t5540-http-push-webdav.sh @@ -201,4 +201,14 @@ test_expect_failure 'push to password-protected repository (no user in URL)' ' test_cmp expect actual ' +test_expect_success 'push to password-protected repository (netrc)' ' + test_commit pw-netrc && + echo "default login user@host password pass@host" >"$HOME/.netrc" && + GIT_TRACE=1 GIT_CURL_VERBOSE=1 git push "$HTTPD_URL/auth/dumb/test_repo.git" HEAD && + git rev-parse --verify HEAD >expect && + git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git" \ + rev-parse --verify HEAD >actual && + test_cmp expect actual +' + test_done diff --git a/t/t5543-atomic-push.sh b/t/t5543-atomic-push.sh index 04b47ad84a..3a700b0676 100755 --- a/t/t5543-atomic-push.sh +++ b/t/t5543-atomic-push.sh @@ -280,4 +280,34 @@ test_expect_success 'atomic push reports (reject by non-ff)' ' test_cmp expect actual ' +test_expect_success 'atomic push reports exit code failure' ' + write_script receive-pack-wrapper <<-\EOF && + git-receive-pack "$@" + exit 1 + EOF + test_must_fail git -C workbench push --atomic \ + --receive-pack="${SQ}$(pwd)${SQ}/receive-pack-wrapper" \ + up HEAD:refs/heads/no-conflict 2>err && + cat >expect <<-EOF && + To ../upstream + * [new branch] HEAD -> no-conflict + error: failed to push some refs to ${SQ}../upstream${SQ} + EOF + test_cmp expect err +' + +test_expect_success 'atomic push reports exit code failure with porcelain' ' + write_script receive-pack-wrapper <<-\EOF && + git-receive-pack "$@" + exit 1 + EOF + test_must_fail git -C workbench push --atomic --porcelain \ + --receive-pack="${SQ}$(pwd)${SQ}/receive-pack-wrapper" \ + up HEAD:refs/heads/no-conflict-porcelain 2>err && + cat >expect <<-EOF && + error: failed to push some refs to ${SQ}../upstream${SQ} + EOF + test_cmp expect err +' + test_done diff --git a/t/t5548-push-porcelain.sh b/t/t5548-push-porcelain.sh index 6282728eaf..4c19404ebe 100755 --- a/t/t5548-push-porcelain.sh +++ b/t/t5548-push-porcelain.sh @@ -54,29 +54,67 @@ format_and_save_expect () { sed -e 's/^> //' -e 's/Z$//' >expect } +create_upstream_template () { + git init --bare upstream-template.git && + git clone upstream-template.git tmp_work_dir && + create_commits_in tmp_work_dir A B && + ( + cd tmp_work_dir && + git push origin \ + $B:refs/heads/main \ + $A:refs/heads/foo \ + $A:refs/heads/bar \ + $A:refs/heads/baz + ) && + rm -rf tmp_work_dir +} + +setup_upstream () { + if test $# -ne 1 + then + BUG "location of upstream repository is not provided" + fi && + rm -rf "$1" && + if ! test -d upstream-template.git + then + create_upstream_template + fi && + git clone --mirror upstream-template.git "$1" && + # The upstream repository provides services using the HTTP protocol. + if ! test "$1" = "upstream.git" + then + git -C "$1" config http.receivepack true + fi +} + setup_upstream_and_workbench () { - # Upstream after setup : main(B) foo(A) bar(A) baz(A) - # Workbench after setup : main(A) + if test $# -ne 1 + then + BUG "location of upstream repository is not provided" + fi + upstream="$1" + + # Upstream after setup: main(B) foo(A) bar(A) baz(A) + # Workbench after setup: main(A) baz(A) next(A) test_expect_success "setup upstream repository and workbench" ' - rm -rf upstream.git workbench && - git init --bare upstream.git && - git init workbench && - create_commits_in workbench A B && + setup_upstream "$upstream" && + rm -rf workbench && + git clone "$upstream" workbench && ( cd workbench && + git update-ref refs/heads/main $A && + git update-ref refs/heads/baz $A && + git update-ref refs/heads/next $A && # Try to make a stable fixed width for abbreviated commit ID, # this fixed-width oid will be replaced with "<OID>". git config core.abbrev 7 && - git remote add origin ../upstream.git && - git update-ref refs/heads/main $A && - git push origin \ - $B:refs/heads/main \ - $A:refs/heads/foo \ - $A:refs/heads/bar \ - $A:refs/heads/baz + git config advice.pushUpdateRejected false ) && - git -C "workbench" config advice.pushUpdateRejected false && - upstream=upstream.git + # The upstream repository provides services using the HTTP protocol. + if ! test "$upstream" = "upstream.git" + then + git -C workbench remote set-url origin "$HTTPD_URL/smart/upstream.git" + fi ' } @@ -88,34 +126,29 @@ run_git_push_porcelain_output_test() { ;; file) PROTOCOL="builtin protocol" - URL_PREFIX="\.\." + URL_PREFIX=".*" ;; esac # Refs of upstream : main(B) foo(A) bar(A) baz(A) # Refs of workbench: main(A) baz(A) next(A) # git-push : main(A) NULL (B) baz(A) next(A) - test_expect_success "porcelain output of successful git-push ($PROTOCOL)" ' - ( - cd workbench && - git update-ref refs/heads/main $A && - git update-ref refs/heads/baz $A && - git update-ref refs/heads/next $A && - git push --porcelain --force origin \ - main \ - :refs/heads/foo \ - $B:bar \ - baz \ - next - ) >out && + test_expect_success ".. git-push --porcelain ($PROTOCOL)" ' + test_when_finished "setup_upstream \"$upstream\"" && + test_must_fail git -C workbench push --porcelain origin \ + main \ + :refs/heads/foo \ + $B:bar \ + baz \ + next >out && make_user_friendly_and_stable_output <out >actual && - format_and_save_expect <<-EOF && + format_and_save_expect <<-\EOF && > To <URL/of/upstream.git> > = refs/heads/baz:refs/heads/baz [up to date] > <COMMIT-B>:refs/heads/bar <COMMIT-A>..<COMMIT-B> > - :refs/heads/foo [deleted] - > + refs/heads/main:refs/heads/main <COMMIT-B>...<COMMIT-A> (forced update) > * refs/heads/next:refs/heads/next [new branch] + > ! refs/heads/main:refs/heads/main [rejected] (non-fast-forward) > Done EOF test_cmp expect actual && @@ -125,34 +158,32 @@ run_git_push_porcelain_output_test() { cat >expect <<-EOF && <COMMIT-B> refs/heads/bar <COMMIT-A> refs/heads/baz - <COMMIT-A> refs/heads/main + <COMMIT-B> refs/heads/main <COMMIT-A> refs/heads/next EOF test_cmp expect actual ' - # Refs of upstream : main(A) bar(B) baz(A) next(A) - # Refs of workbench: main(B) bar(A) baz(A) next(A) - # git-push : main(B) bar(A) NULL next(A) - test_expect_success "atomic push failed ($PROTOCOL)" ' - ( - cd workbench && - git update-ref refs/heads/main $B && - git update-ref refs/heads/bar $A && - test_must_fail git push --atomic --porcelain origin \ - main \ - bar \ - :baz \ - next - ) >out && + # Refs of upstream : main(B) foo(A) bar(A) baz(A) + # Refs of workbench: main(A) baz(A) next(A) + # git-push : main(A) NULL (B) baz(A) next(A) + test_expect_success ".. git-push --porcelain --force ($PROTOCOL)" ' + test_when_finished "setup_upstream \"$upstream\"" && + git -C workbench push --porcelain --force origin \ + main \ + :refs/heads/foo \ + $B:bar \ + baz \ + next >out && make_user_friendly_and_stable_output <out >actual && format_and_save_expect <<-EOF && - To <URL/of/upstream.git> - > = refs/heads/next:refs/heads/next [up to date] - > ! refs/heads/bar:refs/heads/bar [rejected] (non-fast-forward) - > ! (delete):refs/heads/baz [rejected] (atomic push failed) - > ! refs/heads/main:refs/heads/main [rejected] (atomic push failed) - Done + > To <URL/of/upstream.git> + > = refs/heads/baz:refs/heads/baz [up to date] + > <COMMIT-B>:refs/heads/bar <COMMIT-A>..<COMMIT-B> + > - :refs/heads/foo [deleted] + > + refs/heads/main:refs/heads/main <COMMIT-B>...<COMMIT-A> (forced update) + > * refs/heads/next:refs/heads/next [new branch] + > Done EOF test_cmp expect actual && @@ -167,34 +198,129 @@ run_git_push_porcelain_output_test() { test_cmp expect actual ' - test_expect_success "prepare pre-receive hook ($PROTOCOL)" ' - test_hook --setup -C "$upstream" pre-receive <<-EOF - exit 1 + # Refs of upstream : main(B) foo(A) bar(A) baz(A) + # Refs of workbench: main(A) baz(A) next(A) + # git-push : main(A) NULL (B) baz(A) next(A) + test_expect_success ".. git push --porcelain --atomic ($PROTOCOL)" ' + test_when_finished "setup_upstream \"$upstream\"" && + test_must_fail git -C workbench push --porcelain --atomic origin \ + main \ + :refs/heads/foo \ + $B:bar \ + baz \ + next >out && + make_user_friendly_and_stable_output <out >actual && + format_and_save_expect <<-EOF && + > To <URL/of/upstream.git> + > = refs/heads/baz:refs/heads/baz [up to date] + > ! <COMMIT-B>:refs/heads/bar [rejected] (atomic push failed) + > ! (delete):refs/heads/foo [rejected] (atomic push failed) + > ! refs/heads/main:refs/heads/main [rejected] (non-fast-forward) + > ! refs/heads/next:refs/heads/next [rejected] (atomic push failed) + > Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-A> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/foo + <COMMIT-B> refs/heads/main + EOF + test_cmp expect actual + ' + + # Refs of upstream : main(B) foo(A) bar(A) baz(A) + # Refs of workbench: main(A) baz(A) next(A) + # git-push : main(A) NULL (B) baz(A) next(A) + test_expect_success ".. pre-receive hook declined ($PROTOCOL)" ' + test_when_finished "rm -f \"$upstream/hooks/pre-receive\" && + setup_upstream \"$upstream\"" && + test_hook --setup -C "$upstream" pre-receive <<-EOF && + exit 1 + EOF + test_must_fail git -C workbench push --porcelain --force origin \ + main \ + :refs/heads/foo \ + $B:bar \ + baz \ + next >out && + make_user_friendly_and_stable_output <out >actual && + format_and_save_expect <<-EOF && + > To <URL/of/upstream.git> + > = refs/heads/baz:refs/heads/baz [up to date] + > ! <COMMIT-B>:refs/heads/bar [remote rejected] (pre-receive hook declined) + > ! :refs/heads/foo [remote rejected] (pre-receive hook declined) + > ! refs/heads/main:refs/heads/main [remote rejected] (pre-receive hook declined) + > ! refs/heads/next:refs/heads/next [remote rejected] (pre-receive hook declined) + > Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-A> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/foo + <COMMIT-B> refs/heads/main EOF + test_cmp expect actual ' - # Refs of upstream : main(A) bar(B) baz(A) next(A) - # Refs of workbench: main(B) bar(A) baz(A) next(A) - # git-push : main(B) bar(A) NULL next(A) - test_expect_success "pre-receive hook declined ($PROTOCOL)" ' + # Refs of upstream : main(B) foo(A) bar(A) baz(A) + # Refs of workbench: main(A) baz(A) next(A) + # git-push : main(A) next(A) + test_expect_success ".. non-fastforward push ($PROTOCOL)" ' + test_when_finished "setup_upstream \"$upstream\"" && ( cd workbench && - git update-ref refs/heads/main $B && - git update-ref refs/heads/bar $A && - test_must_fail git push --porcelain --force origin \ + test_must_fail git push --porcelain origin \ main \ - bar \ - :baz \ next ) >out && make_user_friendly_and_stable_output <out >actual && format_and_save_expect <<-EOF && - To <URL/of/upstream.git> - > = refs/heads/next:refs/heads/next [up to date] - > ! refs/heads/bar:refs/heads/bar [remote rejected] (pre-receive hook declined) - > ! :refs/heads/baz [remote rejected] (pre-receive hook declined) - > ! refs/heads/main:refs/heads/main [remote rejected] (pre-receive hook declined) - Done + > To <URL/of/upstream.git> + > * refs/heads/next:refs/heads/next [new branch] + > ! refs/heads/main:refs/heads/main [rejected] (non-fast-forward) + > Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-A> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/foo + <COMMIT-B> refs/heads/main + <COMMIT-A> refs/heads/next + EOF + test_cmp expect actual + ' + + # Refs of upstream : main(B) foo(A) bar(A) baz(A) + # Refs of workbench: main(A) baz(A) next(A) + # git-push : main(A) NULL (B) baz(A) next(A) + test_expect_success ".. git push --porcelain --atomic --force ($PROTOCOL)" ' + git -C workbench push --porcelain --atomic --force origin \ + main \ + :refs/heads/foo \ + $B:bar \ + baz \ + next >out && + make_user_friendly_and_stable_output <out >actual && + format_and_save_expect <<-\EOF && + > To <URL/of/upstream.git> + > = refs/heads/baz:refs/heads/baz [up to date] + > <COMMIT-B>:refs/heads/bar <COMMIT-A>..<COMMIT-B> + > - :refs/heads/foo [deleted] + > + refs/heads/main:refs/heads/main <COMMIT-B>...<COMMIT-A> (forced update) + > * refs/heads/next:refs/heads/next [new branch] + > Done EOF test_cmp expect actual && @@ -208,71 +334,174 @@ run_git_push_porcelain_output_test() { EOF test_cmp expect actual ' +} - test_expect_success "remove pre-receive hook ($PROTOCOL)" ' - rm "$upstream/hooks/pre-receive" +run_git_push_dry_run_porcelain_output_test() { + case $1 in + http) + PROTOCOL="HTTP protocol" + URL_PREFIX="http://.*" + ;; + file) + PROTOCOL="builtin protocol" + URL_PREFIX=".*" + ;; + esac + + # Refs of upstream : main(B) foo(A) bar(A) baz(A) + # Refs of workbench: main(A) baz(A) next(A) + # git-push : main(A) NULL (B) baz(A) next(A) + test_expect_success ".. git-push --porcelain --dry-run ($PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain --dry-run origin \ + main \ + :refs/heads/foo \ + $B:bar \ + baz \ + next >out && + make_user_friendly_and_stable_output <out >actual && + format_and_save_expect <<-EOF && + > To <URL/of/upstream.git> + > = refs/heads/baz:refs/heads/baz [up to date] + > <COMMIT-B>:refs/heads/bar <COMMIT-A>..<COMMIT-B> + > - :refs/heads/foo [deleted] + > * refs/heads/next:refs/heads/next [new branch] + > ! refs/heads/main:refs/heads/main [rejected] (non-fast-forward) + > Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-A> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/foo + <COMMIT-B> refs/heads/main + EOF + test_cmp expect actual ' - # Refs of upstream : main(A) bar(B) baz(A) next(A) - # Refs of workbench: main(B) bar(A) baz(A) next(A) - # git-push : main(B) bar(A) NULL next(A) - test_expect_success "non-fastforward push ($PROTOCOL)" ' - ( - cd workbench && - test_must_fail git push --porcelain origin \ - main \ - bar \ - :baz \ - next - ) >out && + # Refs of upstream : main(B) foo(A) bar(A) baz(A) + # Refs of workbench: main(A) baz(A) next(A) + # push : main(A) NULL (B) baz(A) next(A) + test_expect_success ".. git-push --porcelain --dry-run --force ($PROTOCOL)" ' + git -C workbench push --porcelain --dry-run --force origin \ + main \ + :refs/heads/foo \ + $B:bar \ + baz \ + next >out && + make_user_friendly_and_stable_output <out >actual && + format_and_save_expect <<-EOF && + > To <URL/of/upstream.git> + > = refs/heads/baz:refs/heads/baz [up to date] + > <COMMIT-B>:refs/heads/bar <COMMIT-A>..<COMMIT-B> + > - :refs/heads/foo [deleted] + > + refs/heads/main:refs/heads/main <COMMIT-B>...<COMMIT-A> (forced update) + > * refs/heads/next:refs/heads/next [new branch] + > Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-A> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/foo + <COMMIT-B> refs/heads/main + EOF + test_cmp expect actual + ' + + # Refs of upstream : main(B) foo(A) bar(A) baz(A) + # Refs of workbench: main(A) baz(A) next(A) + # git-push : main(A) NULL (B) baz(A) next(A) + test_expect_success ".. git-push --porcelain --dry-run --atomic ($PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain --dry-run --atomic origin \ + main \ + :refs/heads/foo \ + $B:bar \ + baz \ + next >out && make_user_friendly_and_stable_output <out >actual && format_and_save_expect <<-EOF && - To <URL/of/upstream.git> - > = refs/heads/next:refs/heads/next [up to date] - > - :refs/heads/baz [deleted] - > refs/heads/main:refs/heads/main <COMMIT-A>..<COMMIT-B> - > ! refs/heads/bar:refs/heads/bar [rejected] (non-fast-forward) - Done + > To <URL/of/upstream.git> + > = refs/heads/baz:refs/heads/baz [up to date] + > ! <COMMIT-B>:refs/heads/bar [rejected] (atomic push failed) + > ! (delete):refs/heads/foo [rejected] (atomic push failed) + > ! refs/heads/main:refs/heads/main [rejected] (non-fast-forward) + > ! refs/heads/next:refs/heads/next [rejected] (atomic push failed) + > Done EOF test_cmp expect actual && git -C "$upstream" show-ref >out && make_user_friendly_and_stable_output <out >actual && cat >expect <<-EOF && - <COMMIT-B> refs/heads/bar + <COMMIT-A> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/foo + <COMMIT-B> refs/heads/main + EOF + test_cmp expect actual + ' + + # Refs of upstream : main(B) foo(A) bar(A) baz(A) + # Refs of workbench: main(A) baz(A) next(A) + # push : main(A) NULL (B) baz(A) next(A) + test_expect_success ".. git-push --porcelain --dry-run --atomic --force ($PROTOCOL)" ' + git -C workbench push --porcelain --dry-run --atomic --force origin \ + main \ + :refs/heads/foo \ + $B:bar \ + baz \ + next >out && + make_user_friendly_and_stable_output <out >actual && + format_and_save_expect <<-EOF && + > To <URL/of/upstream.git> + > = refs/heads/baz:refs/heads/baz [up to date] + > <COMMIT-B>:refs/heads/bar <COMMIT-A>..<COMMIT-B> + > - :refs/heads/foo [deleted] + > + refs/heads/main:refs/heads/main <COMMIT-B>...<COMMIT-A> (forced update) + > * refs/heads/next:refs/heads/next [new branch] + > Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-A> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/foo <COMMIT-B> refs/heads/main - <COMMIT-A> refs/heads/next EOF test_cmp expect actual ' } -# Initialize the upstream repository and local workbench. -setup_upstream_and_workbench +setup_upstream_and_workbench upstream.git -# Run git-push porcelain test on builtin protocol run_git_push_porcelain_output_test file +setup_upstream_and_workbench upstream.git + +run_git_push_dry_run_porcelain_output_test file + ROOT_PATH="$PWD" . "$TEST_DIRECTORY"/lib-gpg.sh . "$TEST_DIRECTORY"/lib-httpd.sh . "$TEST_DIRECTORY"/lib-terminal.sh start_httpd +setup_askpass_helper -# Re-initialize the upstream repository and local workbench. -setup_upstream_and_workbench - -test_expect_success "setup for http" ' - git -C upstream.git config http.receivepack true && - upstream="$HTTPD_DOCUMENT_ROOT_PATH/upstream.git" && - mv upstream.git "$upstream" && +setup_upstream_and_workbench "$HTTPD_DOCUMENT_ROOT_PATH/upstream.git" - git -C workbench remote set-url origin $HTTPD_URL/smart/upstream.git -' +run_git_push_porcelain_output_test http -setup_askpass_helper +setup_upstream_and_workbench "$HTTPD_DOCUMENT_ROOT_PATH/upstream.git" -# Run git-push porcelain test on HTTP protocol -run_git_push_porcelain_output_test http +run_git_push_dry_run_porcelain_output_test http test_done diff --git a/t/t5620-backfill.sh b/t/t5620-backfill.sh new file mode 100755 index 0000000000..58c81556e7 --- /dev/null +++ b/t/t5620-backfill.sh @@ -0,0 +1,211 @@ +#!/bin/sh + +test_description='git backfill on partial clones' + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +. ./test-lib.sh + +# We create objects in the 'src' repo. +test_expect_success 'setup repo for object creation' ' + echo "{print \$1}" >print_1.awk && + echo "{print \$2}" >print_2.awk && + + git init src && + + mkdir -p src/a/b/c && + mkdir -p src/d/e && + + for i in 1 2 + do + for n in 1 2 3 4 + do + echo "Version $i of file $n" > src/file.$n.txt && + echo "Version $i of file a/$n" > src/a/file.$n.txt && + echo "Version $i of file a/b/$n" > src/a/b/file.$n.txt && + echo "Version $i of file a/b/c/$n" > src/a/b/c/file.$n.txt && + echo "Version $i of file d/$n" > src/d/file.$n.txt && + echo "Version $i of file d/e/$n" > src/d/e/file.$n.txt && + git -C src add . && + git -C src commit -m "Iteration $n" || return 1 + done + done +' + +# Clone 'src' into 'srv.bare' so we have a bare repo to be our origin +# server for the partial clone. +test_expect_success 'setup bare clone for server' ' + git clone --bare "file://$(pwd)/src" srv.bare && + git -C srv.bare config --local uploadpack.allowfilter 1 && + git -C srv.bare config --local uploadpack.allowanysha1inwant 1 +' + +# do basic partial clone from "srv.bare" +test_expect_success 'do partial clone 1, backfill gets all objects' ' + git clone --no-checkout --filter=blob:none \ + --single-branch --branch=main \ + "file://$(pwd)/srv.bare" backfill1 && + + # Backfill with no options gets everything reachable from HEAD. + GIT_TRACE2_EVENT="$(pwd)/backfill-file-trace" git \ + -C backfill1 backfill && + + # We should have engaged the partial clone machinery + test_trace2_data promisor fetch_count 48 <backfill-file-trace && + + # No more missing objects! + git -C backfill1 rev-list --quiet --objects --missing=print HEAD >revs2 && + test_line_count = 0 revs2 +' + +test_expect_success 'do partial clone 2, backfill min batch size' ' + git clone --no-checkout --filter=blob:none \ + --single-branch --branch=main \ + "file://$(pwd)/srv.bare" backfill2 && + + GIT_TRACE2_EVENT="$(pwd)/batch-trace" git \ + -C backfill2 backfill --min-batch-size=20 && + + # Batches were used + test_trace2_data promisor fetch_count 20 <batch-trace >matches && + test_line_count = 2 matches && + test_trace2_data promisor fetch_count 8 <batch-trace && + + # No more missing objects! + git -C backfill2 rev-list --quiet --objects --missing=print HEAD >revs2 && + test_line_count = 0 revs2 +' + +test_expect_success 'backfill --sparse without sparse-checkout fails' ' + git init not-sparse && + test_must_fail git -C not-sparse backfill --sparse 2>err && + grep "problem loading sparse-checkout" err +' + +test_expect_success 'backfill --sparse' ' + git clone --sparse --filter=blob:none \ + --single-branch --branch=main \ + "file://$(pwd)/srv.bare" backfill3 && + + # Initial checkout includes four files at root. + git -C backfill3 rev-list --quiet --objects --missing=print HEAD >missing && + test_line_count = 44 missing && + + # Initial sparse-checkout is just the files at root, so we get the + # older versions of the four files at tip. + GIT_TRACE2_EVENT="$(pwd)/sparse-trace1" git \ + -C backfill3 backfill --sparse && + test_trace2_data promisor fetch_count 4 <sparse-trace1 && + test_trace2_data path-walk paths 5 <sparse-trace1 && + git -C backfill3 rev-list --quiet --objects --missing=print HEAD >missing && + test_line_count = 40 missing && + + # Expand the sparse-checkout to include 'd' recursively. This + # engages the algorithm to skip the trees for 'a'. Note that + # the "sparse-checkout set" command downloads the objects at tip + # to satisfy the current checkout. + git -C backfill3 sparse-checkout set d && + GIT_TRACE2_EVENT="$(pwd)/sparse-trace2" git \ + -C backfill3 backfill --sparse && + test_trace2_data promisor fetch_count 8 <sparse-trace2 && + test_trace2_data path-walk paths 15 <sparse-trace2 && + git -C backfill3 rev-list --quiet --objects --missing=print HEAD >missing && + test_line_count = 24 missing && + + # Disabling the --sparse option (on by default) will download everything + git -C backfill3 backfill --no-sparse && + git -C backfill3 rev-list --quiet --objects --missing=print HEAD >missing && + test_line_count = 0 missing +' + +test_expect_success 'backfill --sparse without cone mode (positive)' ' + git clone --no-checkout --filter=blob:none \ + --single-branch --branch=main \ + "file://$(pwd)/srv.bare" backfill4 && + + # No blobs yet + git -C backfill4 rev-list --quiet --objects --missing=print HEAD >missing && + test_line_count = 48 missing && + + # Define sparse-checkout by filename regardless of parent directory. + # This downloads 6 blobs to satisfy the checkout. + git -C backfill4 sparse-checkout set --no-cone "**/file.1.txt" && + git -C backfill4 checkout main && + + # Track new blob count + git -C backfill4 rev-list --quiet --objects --missing=print HEAD >missing && + test_line_count = 42 missing && + + GIT_TRACE2_EVENT="$(pwd)/no-cone-trace1" git \ + -C backfill4 backfill --sparse && + test_trace2_data promisor fetch_count 6 <no-cone-trace1 && + + # This walk needed to visit all directories to search for these paths. + test_trace2_data path-walk paths 12 <no-cone-trace1 && + git -C backfill4 rev-list --quiet --objects --missing=print HEAD >missing && + test_line_count = 36 missing +' + +test_expect_success 'backfill --sparse without cone mode (negative)' ' + git clone --no-checkout --filter=blob:none \ + --single-branch --branch=main \ + "file://$(pwd)/srv.bare" backfill5 && + + # No blobs yet + git -C backfill5 rev-list --quiet --objects --missing=print HEAD >missing && + test_line_count = 48 missing && + + # Define sparse-checkout by filename regardless of parent directory. + # This downloads 18 blobs to satisfy the checkout + git -C backfill5 sparse-checkout set --no-cone "**/file*" "!**/file.1.txt" && + git -C backfill5 checkout main && + + # Track new blob count + git -C backfill5 rev-list --quiet --objects --missing=print HEAD >missing && + test_line_count = 30 missing && + + GIT_TRACE2_EVENT="$(pwd)/no-cone-trace2" git \ + -C backfill5 backfill --sparse && + test_trace2_data promisor fetch_count 18 <no-cone-trace2 && + + # This walk needed to visit all directories to search for these paths, plus + # 12 extra "file.?.txt" paths than the previous test. + test_trace2_data path-walk paths 24 <no-cone-trace2 && + git -C backfill5 rev-list --quiet --objects --missing=print HEAD >missing && + test_line_count = 12 missing +' + +. "$TEST_DIRECTORY"/lib-httpd.sh +start_httpd + +test_expect_success 'create a partial clone over HTTP' ' + SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" && + rm -rf "$SERVER" repo && + git clone --bare "file://$(pwd)/src" "$SERVER" && + test_config -C "$SERVER" uploadpack.allowfilter 1 && + test_config -C "$SERVER" uploadpack.allowanysha1inwant 1 && + + git clone --no-checkout --filter=blob:none \ + "$HTTPD_URL/smart/server" backfill-http +' + +test_expect_success 'backfilling over HTTP succeeds' ' + GIT_TRACE2_EVENT="$(pwd)/backfill-http-trace" git \ + -C backfill-http backfill && + + # We should have engaged the partial clone machinery + test_trace2_data promisor fetch_count 48 <backfill-http-trace && + + # Confirm all objects are present, none missing. + git -C backfill-http rev-list --objects --all >rev-list-out && + awk "{print \$1;}" <rev-list-out >oids && + GIT_TRACE2_EVENT="$(pwd)/walk-trace" git -C backfill-http \ + cat-file --batch-check <oids >batch-out && + ! grep missing batch-out +' + +# DO NOT add non-httpd-specific tests here, because the last part of this +# test script is only executed when httpd is available and enabled. + +test_done diff --git a/t/t5621-clone-revision.sh b/t/t5621-clone-revision.sh new file mode 100755 index 0000000000..db3b8cff55 --- /dev/null +++ b/t/t5621-clone-revision.sh @@ -0,0 +1,122 @@ +#!/bin/sh + +test_description='tests for git clone --revision' +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit --no-tag "initial commit" README "Hello" && + test_commit --annotate "second commit" README "Hello world" v1.0 && + test_commit --no-tag "third commit" README "Hello world!" && + git switch -c feature v1.0 && + test_commit --no-tag "feature commit" README "Hello world!" && + git switch main +' + +test_expect_success 'clone with --revision being a branch' ' + test_when_finished "rm -rf dst" && + git clone --revision=refs/heads/feature . dst && + git rev-parse refs/heads/feature >expect && + git -C dst rev-parse HEAD >actual && + test_must_fail git -C dst symbolic-ref -q HEAD >/dev/null && + test_cmp expect actual && + git -C dst for-each-ref refs >expect && + test_must_be_empty expect && + test_must_fail git -C dst config remote.origin.fetch +' + +test_expect_success 'clone with --depth and --revision being a branch' ' + test_when_finished "rm -rf dst" && + git clone --no-local --depth=1 --revision=refs/heads/feature . dst && + git rev-parse refs/heads/feature >expect && + git -C dst rev-parse HEAD >actual && + test_must_fail git -C dst symbolic-ref -q HEAD >/dev/null && + test_cmp expect actual && + git -C dst for-each-ref refs >expect && + test_must_be_empty expect && + test_must_fail git -C dst config remote.origin.fetch && + git -C dst rev-list HEAD >actual && + test_line_count = 1 actual +' + +test_expect_success 'clone with --revision being a tag' ' + test_when_finished "rm -rf dst" && + git clone --revision=refs/tags/v1.0 . dst && + git rev-parse refs/tags/v1.0^{} >expect && + git -C dst rev-parse HEAD >actual && + test_must_fail git -C dst symbolic-ref -q HEAD >/dev/null && + test_cmp expect actual && + git -C dst for-each-ref refs >expect && + test_must_be_empty expect && + test_must_fail git -C dst config remote.origin.fetch +' + +test_expect_success 'clone with --revision being HEAD' ' + test_when_finished "rm -rf dst" && + git clone --revision=HEAD . dst && + git rev-parse HEAD >expect && + git -C dst rev-parse HEAD >actual && + test_must_fail git -C dst symbolic-ref -q HEAD >/dev/null && + test_cmp expect actual && + git -C dst for-each-ref refs >expect && + test_must_be_empty expect && + test_must_fail git -C dst config remote.origin.fetch +' + +test_expect_success 'clone with --revision being a raw commit hash' ' + test_when_finished "rm -rf dst" && + oid=$(git rev-parse refs/heads/feature) && + git clone --revision=$oid . dst && + echo $oid >expect && + git -C dst rev-parse HEAD >actual && + test_must_fail git -C dst symbolic-ref -q HEAD >/dev/null && + test_cmp expect actual && + git -C dst for-each-ref refs >expect && + test_must_be_empty expect && + test_must_fail git -C dst config remote.origin.fetch +' + +test_expect_success 'clone with --revision and --bare' ' + test_when_finished "rm -rf dst" && + git clone --revision=refs/heads/main --bare . dst && + oid=$(git rev-parse refs/heads/main) && + git -C dst cat-file -t $oid >actual && + echo "commit" >expect && + test_cmp expect actual && + git -C dst for-each-ref refs >expect && + test_must_be_empty expect && + test_must_fail git -C dst config remote.origin.fetch +' + +test_expect_success 'clone with --revision being a short raw commit hash' ' + test_when_finished "rm -rf dst" && + oid=$(git rev-parse --short refs/heads/feature) && + test_must_fail git clone --revision=$oid . dst 2>err && + test_grep "fatal: Remote revision $oid not found in upstream origin" err +' + +test_expect_success 'clone with --revision being a tree hash' ' + test_when_finished "rm -rf dst" && + oid=$(git rev-parse refs/heads/feature^{tree}) && + test_must_fail git clone --revision=$oid . dst 2>err && + test_grep "error: object $oid is a tree, not a commit" err +' + +test_expect_success 'clone with --revision being the parent of a ref fails' ' + test_when_finished "rm -rf dst" && + test_must_fail git clone --revision=refs/heads/main^ . dst +' + +test_expect_success 'clone with --revision and --branch fails' ' + test_when_finished "rm -rf dst" && + test_must_fail git clone --revision=refs/heads/main --branch=main . dst +' + +test_expect_success 'clone with --revision and --mirror fails' ' + test_when_finished "rm -rf dst" && + test_must_fail git clone --revision=refs/heads/main --mirror . dst +' + +test_done diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh index de904c1655..678a346ed0 100755 --- a/t/t5701-git-serve.sh +++ b/t/t5701-git-serve.sh @@ -7,24 +7,40 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh -test_expect_success 'test capability advertisement' ' +test_expect_success 'setup to generate files with expected content' ' + printf "agent=git/%s" "$(git version | cut -d" " -f3)" >agent_capability && + test_oid_cache <<-EOF && wrong_algo sha1:sha256 wrong_algo sha256:sha1 EOF + + if test_have_prereq WINDOWS + then + printf "agent=FAKE\n" >agent_capability + else + printf -- "-%s\n" $(uname -s | test_redact_non_printables) >>agent_capability + fi && cat >expect.base <<-EOF && version 2 - agent=git/$(git version | cut -d" " -f3) + $(cat agent_capability) ls-refs=unborn fetch=shallow wait-for-done server-option object-format=$(test_oid algo) EOF - cat >expect.trailer <<-EOF && + cat >expect.trailer <<-EOF 0000 EOF +' + +test_expect_success 'test capability advertisement' ' cat expect.base expect.trailer >expect && + if test_have_prereq WINDOWS + then + GIT_USER_AGENT=FAKE && export GIT_USER_AGENT + fi && GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \ --advertise-capabilities >out && test-tool pkt-line unpack <out >actual && @@ -355,6 +371,10 @@ test_expect_success 'test capability advertisement with uploadpack.advertiseBund expect.extra \ expect.trailer >expect && + if test_have_prereq WINDOWS + then + GIT_USER_AGENT=FAKE && export GIT_USER_AGENT + fi && GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \ --advertise-capabilities >out && test-tool pkt-line unpack <out >actual && diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index d3df81e785..4d0cbe9872 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -665,7 +665,7 @@ test_expect_success 'even with handcrafted request, filter does not work if not test-tool -C server serve-v2 --stateless-rpc <in >/dev/null ' -test_expect_success 'default refspec is used to filter ref when fetchcing' ' +test_expect_success 'default refspec is used to filter ref when fetching' ' test_when_finished "rm -f log" && GIT_TRACE_PACKET="$(pwd)/log" git -C file_child -c protocol.version=2 \ @@ -679,6 +679,48 @@ test_expect_success 'default refspec is used to filter ref when fetchcing' ' grep "ref-prefix refs/tags/" log ' +test_expect_success 'set up parent for prefix tests' ' + git init prefix-parent && + git -C prefix-parent commit --allow-empty -m foo && + git -C prefix-parent tag my-tag && + git -C prefix-parent branch unrelated-branch +' + +test_expect_success 'empty refspec filters refs when fetching' ' + git init configless-child && + + test_when_finished "rm -f log" && + GIT_TRACE_PACKET="$(pwd)/log" \ + git -C configless-child fetch ../prefix-parent && + test_grep ! unrelated-branch log +' + +test_expect_success 'exact oid fetch with tag following' ' + git init exact-oid-tags && + + commit=$(git -C prefix-parent rev-parse --verify HEAD) && + + test_when_finished "rm -f log" && + GIT_TRACE_PACKET="$(pwd)/log" \ + git -C exact-oid-tags fetch ../prefix-parent \ + $commit:refs/heads/exact && + test_grep ! unrelated-branch log && + git -C exact-oid-tags rev-parse --verify my-tag +' + +test_expect_success 'exact oid fetch avoids pointless HEAD request' ' + git init exact-oid-head && + git -C exact-oid-head remote add origin ../prefix-parent && + + commit=$(git -C prefix-parent rev-parse --verify HEAD) && + + test_when_finished "rm -f log" && + GIT_TRACE_PACKET="$(pwd)/log" \ + git -C exact-oid-head fetch --no-tags origin \ + $commit:refs/heads/exact && + test_grep ! command=ls-refs log +' + test_expect_success 'fetch supports various ways of have lines' ' rm -rf server client trace && git init server && diff --git a/t/t5710-promisor-remote-capability.sh b/t/t5710-promisor-remote-capability.sh new file mode 100755 index 0000000000..d2cc69a17e --- /dev/null +++ b/t/t5710-promisor-remote-capability.sh @@ -0,0 +1,312 @@ +#!/bin/sh + +test_description='handling of promisor remote advertisement' + +. ./test-lib.sh + +GIT_TEST_MULTI_PACK_INDEX=0 +GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0 + +# Setup the repository with three commits, this way HEAD is always +# available and we can hide commit 1 or 2. +test_expect_success 'setup: create "template" repository' ' + git init template && + test_commit -C template 1 && + test_commit -C template 2 && + test_commit -C template 3 && + test-tool genrandom foo 10240 >template/foo && + git -C template add foo && + git -C template commit -m foo +' + +# A bare repo will act as a server repo with unpacked objects. +test_expect_success 'setup: create bare "server" repository' ' + git clone --bare --no-local template server && + mv server/objects/pack/pack-* . && + packfile=$(ls pack-*.pack) && + git -C server unpack-objects --strict <"$packfile" +' + +check_missing_objects () { + git -C "$1" rev-list --objects --all --missing=print > all.txt && + perl -ne 'print if s/^[?]//' all.txt >missing.txt && + test_line_count = "$2" missing.txt && + if test "$2" -lt 2 + then + test "$3" = "$(cat missing.txt)" + else + test -f "$3" && + sort <"$3" >expected_sorted && + sort <missing.txt >actual_sorted && + test_cmp expected_sorted actual_sorted + fi +} + +initialize_server () { + count="$1" + missing_oids="$2" + + # Repack everything first + git -C server -c repack.writebitmaps=false repack -a -d && + + # Remove promisor file in case they exist, useful when reinitializing + rm -rf server/objects/pack/*.promisor && + + # Repack without the largest object and create a promisor pack on server + git -C server -c repack.writebitmaps=false repack -a -d \ + --filter=blob:limit=5k --filter-to="$(pwd)/pack" && + promisor_file=$(ls server/objects/pack/*.pack | sed "s/\.pack/.promisor/") && + >"$promisor_file" && + + # Check objects missing on the server + check_missing_objects server "$count" "$missing_oids" +} + +copy_to_lop () { + oid_path="$(test_oid_to_path $1)" && + path="server/objects/$oid_path" && + path2="lop/objects/$oid_path" && + mkdir -p $(dirname "$path2") && + cp "$path" "$path2" +} + +test_expect_success "setup for testing promisor remote advertisement" ' + # Create another bare repo called "lop" (for Large Object Promisor) + git init --bare lop && + + # Copy the largest object from server to lop + obj="HEAD:foo" && + oid="$(git -C server rev-parse $obj)" && + copy_to_lop "$oid" && + + initialize_server 1 "$oid" && + + # Configure lop as promisor remote for server + git -C server remote add lop "file://$(pwd)/lop" && + git -C server config remote.lop.promisor true && + + git -C lop config uploadpack.allowFilter true && + git -C lop config uploadpack.allowAnySHA1InWant true && + git -C server config uploadpack.allowFilter true && + git -C server config uploadpack.allowAnySHA1InWant true +' + +test_expect_success "clone with promisor.advertise set to 'true'" ' + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=All \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + +test_expect_success "clone with promisor.advertise set to 'false'" ' + git -C server config promisor.advertise false && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=All \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is not missing on the server + check_missing_objects server 0 "" && + + # Reinitialize server so that the largest object is missing again + initialize_server 1 "$oid" +' + +test_expect_success "clone with promisor.acceptfromserver set to 'None'" ' + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=None \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is not missing on the server + check_missing_objects server 0 "" && + + # Reinitialize server so that the largest object is missing again + initialize_server 1 "$oid" +' + +test_expect_success "init + fetch with promisor.advertise set to 'true'" ' + git -C server config promisor.advertise true && + + test_when_finished "rm -rf client" && + mkdir client && + git -C client init && + git -C client config remote.lop.promisor true && + git -C client config remote.lop.fetch "+refs/heads/*:refs/remotes/lop/*" && + git -C client config remote.lop.url "file://$(pwd)/lop" && + git -C client config remote.server.url "file://$(pwd)/server" && + git -C client config remote.server.fetch "+refs/heads/*:refs/remotes/server/*" && + git -C client config promisor.acceptfromserver All && + GIT_NO_LAZY_FETCH=0 git -C client fetch --filter="blob:limit=5k" server && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + +test_expect_success "clone with promisor.acceptfromserver set to 'KnownName'" ' + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=KnownName \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + +test_expect_success "clone with 'KnownName' and different remote names" ' + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.serverTwo.promisor=true \ + -c remote.serverTwo.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.serverTwo.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=KnownName \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is not missing on the server + check_missing_objects server 0 "" && + + # Reinitialize server so that the largest object is missing again + initialize_server 1 "$oid" +' + +test_expect_success "clone with promisor.acceptfromserver set to 'KnownUrl'" ' + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=KnownUrl \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + +test_expect_success "clone with 'KnownUrl' and different remote urls" ' + ln -s lop serverTwo && + + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/serverTwo" \ + -c promisor.acceptfromserver=KnownUrl \ + --no-local --filter="blob:limit=5k" server client && + test_when_finished "rm -rf client" && + + # Check that the largest object is not missing on the server + check_missing_objects server 0 "" && + + # Reinitialize server so that the largest object is missing again + initialize_server 1 "$oid" +' + +test_expect_success "clone with promisor.advertise set to 'true' but don't delete the client" ' + git -C server config promisor.advertise true && + + # Clone from server to create a client + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=All \ + --no-local --filter="blob:limit=5k" server client && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + +test_expect_success "setup for subsequent fetches" ' + # Generate new commit with large blob + test-tool genrandom bar 10240 >template/bar && + git -C template add bar && + git -C template commit -m bar && + + # Fetch new commit with large blob + git -C server fetch origin && + git -C server update-ref HEAD FETCH_HEAD && + git -C server rev-parse HEAD >expected_head && + + # Repack everything twice and remove .promisor files before + # each repack. This makes sure everything gets repacked + # into a single packfile. The second repack is necessary + # because the first one fetches from lop and creates a new + # packfile and its associated .promisor file. + + rm -f server/objects/pack/*.promisor && + git -C server -c repack.writebitmaps=false repack -a -d && + rm -f server/objects/pack/*.promisor && + git -C server -c repack.writebitmaps=false repack -a -d && + + # Unpack everything + rm pack-* && + mv server/objects/pack/pack-* . && + packfile=$(ls pack-*.pack) && + git -C server unpack-objects --strict <"$packfile" && + + # Copy new large object to lop + obj_bar="HEAD:bar" && + oid_bar="$(git -C server rev-parse $obj_bar)" && + copy_to_lop "$oid_bar" && + + # Reinitialize server so that the 2 largest objects are missing + printf "%s\n" "$oid" "$oid_bar" >expected_missing.txt && + initialize_server 2 expected_missing.txt && + + # Create one more client + cp -r client client2 +' + +test_expect_success "subsequent fetch from a client when promisor.advertise is true" ' + git -C server config promisor.advertise true && + + GIT_NO_LAZY_FETCH=0 git -C client pull origin && + + git -C client rev-parse HEAD >actual && + test_cmp expected_head actual && + + cat client/bar >/dev/null && + + check_missing_objects server 2 expected_missing.txt +' + +test_expect_success "subsequent fetch from a client when promisor.advertise is false" ' + git -C server config promisor.advertise false && + + GIT_NO_LAZY_FETCH=0 git -C client2 pull origin && + + git -C client2 rev-parse HEAD >actual && + test_cmp expected_head actual && + + cat client2/bar >/dev/null && + + check_missing_objects server 1 "$oid" +' + +test_done diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh index de1e87f162..4cecb6224c 100755 --- a/t/t6012-rev-list-simplify.sh +++ b/t/t6012-rev-list-simplify.sh @@ -177,7 +177,7 @@ test_expect_success '--full-diff is not affected by --parents' ' # \ / /\ / # `---X--' `---Y--' # -# This example is explained in Documentation/rev-list-options.txt +# This example is explained in Documentation/rev-list-options.adoc test_expect_success 'setup rebuild repo' ' rm -rf .git * && diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh index 4ce62feaa2..b3807e8f35 100755 --- a/t/t6020-bundle-misc.sh +++ b/t/t6020-bundle-misc.sh @@ -246,7 +246,11 @@ test_expect_success 'create bundle with --since option' ' EOF test_cmp expect actual && - git bundle create since.bdl \ + # If a different name hash function is used, then one fewer + # delta base is found and this counts a different number + # of objects after performing --fix-thin. + GIT_TEST_NAME_HASH_VERSION=1 \ + git bundle create since.bdl \ --since "Thu Apr 7 15:27:00 2005 -0700" \ --all && diff --git a/t/t6022-rev-list-missing.sh b/t/t6022-rev-list-missing.sh index 7553a9cca2..3e2790d4c8 100755 --- a/t/t6022-rev-list-missing.sh +++ b/t/t6022-rev-list-missing.sh @@ -145,4 +145,57 @@ do done done +for obj in "HEAD~1" "HEAD^{tree}" "HEAD:foo" "HEAD:foo/bar" "HEAD:baz baz" +do + test_expect_success "--missing=print-info with missing '$obj'" ' + test_when_finished rm -rf missing-info && + + git init missing-info && + ( + cd missing-info && + git commit --allow-empty -m first && + + mkdir foo && + echo bar >foo/bar && + echo baz >"baz baz" && + echo bat >bat\" && + git add -A && + git commit -m second && + + oid="$(git rev-parse "$obj")" && + path=".git/objects/$(test_oid_to_path $oid)" && + type_info=" type=$(git cat-file -t $oid)" && + + case $obj in + HEAD:foo) + path_info=" path=foo" + ;; + HEAD:foo/bar) + path_info=" path=foo/bar" + ;; + "HEAD:baz baz") + path_info=" path=\"baz baz\"" + ;; + "HEAD:bat\"") + path_info=" path=\"bat\\\"\"" + ;; + esac && + + # Before the object is made missing, we use rev-list to + # get the expected oids. + git rev-list --objects --no-object-names \ + HEAD ^"$obj" >expect.raw && + echo "?$oid$path_info$type_info" >>expect.raw && + + mv "$path" "$path.hidden" && + git rev-list --objects --no-object-names \ + --missing=print-info HEAD >actual.raw && + + sort actual.raw >actual && + sort expect.raw >expect && + test_cmp expect actual + ) + ' +done + test_done diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index 3f6160d702..76843a6169 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -82,11 +82,13 @@ check_describe R-2-gHASH HEAD^^ check_describe A-3-gHASH HEAD^^2 check_describe B HEAD^^2^ check_describe R-1-gHASH HEAD^^^ +check_describe R-1-gHASH R-1-g$(git rev-parse --short HEAD^^)~1 check_describe c-7-gHASH --tags HEAD check_describe c-6-gHASH --tags HEAD^ check_describe e-1-gHASH --tags HEAD^^ check_describe c-2-gHASH --tags HEAD^^2 +check_describe c-2-gHASH --tags c-2-g$(git rev-parse --short HEAD^^2)^0 check_describe B --tags HEAD^^2^ check_describe e --tags HEAD^^^ check_describe e --tags --exact-match HEAD^^^ @@ -725,4 +727,26 @@ test_expect_success '--exact-match does not show --always fallback' ' test_must_fail git describe --exact-match --always ' +test_expect_success 'avoid being fooled by describe-like filename' ' + test_when_finished rm out && + + git rev-parse --short HEAD >out && + FILENAME=filename-g$(cat out) && + touch $FILENAME && + git add $FILENAME && + git commit -m "Add $FILENAME" && + + git cat-file -t HEAD:$FILENAME >actual && + + echo blob >expect && + test_cmp expect actual +' + +test_expect_success 'do not be fooled by invalid describe format ' ' + test_when_finished rm out && + + git rev-parse --short HEAD >out && + test_must_fail git cat-file -t "refs/tags/super-invalid/./../...../ ~^:/?*[////\\\\\\&}/busted.lock-42-g"$(cat out) +' + test_done diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index a5c7794385..9b4f4306c4 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -292,6 +292,13 @@ test_expect_success 'Check invalid atoms names are errors' ' test_must_fail git for-each-ref --format="%(INVALID)" refs/heads ' +test_expect_success 'for-each-ref does not crash with -h' ' + test_expect_code 129 git for-each-ref -h >usage && + test_grep "[Uu]sage: git for-each-ref " usage && + test_expect_code 129 nongit git for-each-ref -h >usage && + test_grep "[Uu]sage: git for-each-ref " usage +' + test_expect_success 'Check format specifiers are ignored in naming date atoms' ' git for-each-ref --format="%(authordate)" refs/heads && git for-each-ref --format="%(authordate:default) %(authordate)" refs/heads && diff --git a/t/t6423-merge-rename-directories.sh b/t/t6423-merge-rename-directories.sh index 88d1cf2cde..79d889b94c 100755 --- a/t/t6423-merge-rename-directories.sh +++ b/t/t6423-merge-rename-directories.sh @@ -5071,7 +5071,8 @@ test_expect_success '12i: Directory rename causes rename-to-self' ' test_path_is_file source/bar && test_path_is_file source/baz && - git ls-files | uniq >tracked && + git ls-files >actual && + uniq <actual >tracked && test_line_count = 3 tracked && git status --porcelain -uno >actual && @@ -5129,7 +5130,8 @@ test_expect_success '12j: Directory rename to root causes rename-to-self' ' test_path_is_file bar && test_path_is_file baz && - git ls-files | uniq >tracked && + git ls-files >actual && + uniq <actual >tracked && test_line_count = 3 tracked && git status --porcelain -uno >actual && @@ -5187,7 +5189,8 @@ test_expect_success '12k: Directory rename with sibling causes rename-to-self' ' test_path_is_file dirA/bar && test_path_is_file dirA/baz && - git ls-files | uniq >tracked && + git ls-files >actual && + uniq <actual >tracked && test_line_count = 3 tracked && git status --porcelain -uno >actual && @@ -5360,6 +5363,47 @@ test_expect_merge_algorithm failure success '12m: Change parent of renamed-dir t ) ' +test_setup_12n () { + git init 12n && + ( + cd 12n && + + mkdir tools && + echo hello >tools/hello && + git add tools/hello && + git commit -m "O" && + + git branch O && + git branch A && + git branch B && + + git switch A && + echo world >world && + git add world && + git commit -q world -m 'Add world' && + + git mv world tools/world && + git commit -m "Move world into tools/" && + + git switch B && + git mv tools/hello hello && + git commit -m "Move hello from tools/ to toplevel" + ) +} + +test_expect_success '12n: Directory rename transitively makes rename back to self' ' + test_setup_12n && + ( + cd 12n && + + git checkout -q B^0 && + + test_must_fail git cherry-pick A^0 >out && + grep "CONFLICT (file location).*should perhaps be moved" out + ) +' + + ########################################################################### # SECTION 13: Checking informational and conflict messages # diff --git a/t/t6427-diff3-conflict-markers.sh b/t/t6427-diff3-conflict-markers.sh index dd5fe6a402..57569c4f4b 100755 --- a/t/t6427-diff3-conflict-markers.sh +++ b/t/t6427-diff3-conflict-markers.sh @@ -207,7 +207,7 @@ test_expect_success 'rebase --apply describes fake ancestor base' ' cd rebase && git rebase --abort && test_must_fail git -c merge.conflictstyle=diff3 rebase --apply main && - grep "||||||| constructed merge base" file + grep "||||||| constructed fake ancestor" file ) ' diff --git a/t/t6434-merge-recursive-rename-options.sh b/t/t6434-merge-recursive-rename-options.sh index a11707835b..6e913c30a1 100755 --- a/t/t6434-merge-recursive-rename-options.sh +++ b/t/t6434-merge-recursive-rename-options.sh @@ -22,7 +22,7 @@ R075 2-old 2-new R100 3-old 3-new Actual similarity indices are parsed from diff output. We rely on the fact that -they are rounded down (see, e.g., Documentation/diff-generate-patch.txt, which +they are rounded down (see, e.g., Documentation/diff-generate-patch.adoc, which mentions this in a different context). ' diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh index 5378455968..bef472cb8d 100755 --- a/t/t6500-gc.sh +++ b/t/t6500-gc.sh @@ -338,6 +338,39 @@ test_expect_success 'gc.maxCruftSize sets appropriate repack options' ' test_subcommand $cruft_max_size_opts --max-cruft-size=3145728 <trace2.txt ' +test_expect_success '--expire-to sets repack --expire-to' ' + rm -rf expired && + mkdir expired && + expire_to="$(pwd)/expired/pack" && + GIT_TRACE2_EVENT=$(pwd)/trace2.txt git -C cruft--max-size gc --cruft --expire-to="$expire_to" && + test_subcommand $cruft_max_size_opts --expire-to="$expire_to" <trace2.txt +' + +test_expect_success '--expire-to with --prune=now sets repack --expire-to' ' + rm -rf expired && + mkdir expired && + expire_to="$(pwd)/expired/pack" && + GIT_TRACE2_EVENT=$(pwd)/trace2.txt git -C cruft--max-size gc --cruft --prune=now --expire-to="$expire_to" && + test_subcommand git repack -d -l --cruft --cruft-expiration=now --expire-to="$expire_to" <trace2.txt +' + + +test_expect_success '--expire-to with --no-cruft sets repack -A' ' + rm -rf expired && + mkdir expired && + expire_to="$(pwd)/expired/pack" && + GIT_TRACE2_EVENT=$(pwd)/trace2.txt git -C cruft--max-size gc --no-cruft --expire-to="$expire_to" && + test_subcommand git repack -d -l -A --unpack-unreachable=2.weeks.ago <trace2.txt +' + +test_expect_success '--expire-to with --no-cruft sets repack -a' ' + rm -rf expired && + mkdir expired && + expire_to="$(pwd)/expired/pack" && + GIT_TRACE2_EVENT=$(pwd)/trace2.txt git -C cruft--max-size gc --no-cruft --prune=now --expire-to="$expire_to" && + test_subcommand git repack -d -l -a <trace2.txt +' + run_and_wait_for_gc () { # We read stdout from gc for the side effect of waiting until the # background gc process exits, closing its fd 9. Furthermore, the diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh index 2591f8b8b3..6638d1aa1d 100755 --- a/t/t6600-test-reach.sh +++ b/t/t6600-test-reach.sh @@ -733,4 +733,33 @@ test_expect_success 'for-each-ref is-base:multiple' ' --format="%(refname)[%(is-base:commit-2-3)-%(is-base:commit-6-5)]" --stdin ' +test_expect_success 'for-each-ref is-base: --sort' ' + cat >input <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-4-2 + refs/heads/commit-4-4 + refs/heads/commit-8-4 + EOF + + cat >expect <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-4-4 + refs/heads/commit-8-4 + refs/heads/commit-4-2 + EOF + run_all_modes git for-each-ref \ + --format="%(refname)" --stdin \ + --sort=refname --sort=is-base:commit-2-3 && + + cat >expect <<-\EOF && + refs/heads/commit-4-2 + refs/heads/commit-1-1 + refs/heads/commit-4-4 + refs/heads/commit-8-4 + EOF + run_all_modes git for-each-ref \ + --format="%(refname)" --stdin \ + --sort=refname --sort=-is-base:commit-2-3 +' + test_done diff --git a/t/t6601-path-walk.sh b/t/t6601-path-walk.sh new file mode 100755 index 0000000000..c89b0f1e19 --- /dev/null +++ b/t/t6601-path-walk.sh @@ -0,0 +1,400 @@ +#!/bin/sh + +TEST_PASSES_SANITIZE_LEAK=true + +test_description='direct path-walk API tests' + +. ./test-lib.sh + +test_expect_success 'setup test repository' ' + git checkout -b base && + + # Make some objects that will only be reachable + # via non-commit tags. + mkdir child && + echo file >child/file && + git add child && + git commit -m "will abandon" && + git tag -a -m "tree" tree-tag HEAD^{tree} && + echo file2 >file2 && + git add file2 && + git commit --amend -m "will abandon" && + git tag tree-tag2 HEAD^{tree} && + + echo blob >file && + blob_oid=$(git hash-object -t blob -w --stdin <file) && + git tag -a -m "blob" blob-tag "$blob_oid" && + echo blob2 >file2 && + blob2_oid=$(git hash-object -t blob -w --stdin <file2) && + git tag blob-tag2 "$blob2_oid" && + + rm -fr child file file2 && + + mkdir left && + mkdir right && + echo a >a && + echo b >left/b && + echo c >right/c && + git add . && + git commit --amend -m "first" && + git tag -m "first" first HEAD && + + echo d >right/d && + git add right && + git commit -m "second" && + git tag -a -m "second (under)" second.1 HEAD && + git tag -a -m "second (top)" second.2 second.1 && + + # Set up file/dir collision in history. + rm a && + mkdir a && + echo a >a/a && + echo bb >left/b && + git add a left && + git commit -m "third" && + git tag -a -m "third" third && + + git checkout -b topic HEAD~1 && + echo cc >right/c && + git commit -a -m "topic" && + git tag -a -m "fourth" fourth +' + +test_expect_success 'all' ' + test-tool path-walk -- --all >out && + + cat >expect <<-EOF && + 0:commit::$(git rev-parse topic) + 0:commit::$(git rev-parse base) + 0:commit::$(git rev-parse base~1) + 0:commit::$(git rev-parse base~2) + 1:tag:/tags:$(git rev-parse refs/tags/first) + 1:tag:/tags:$(git rev-parse refs/tags/second.1) + 1:tag:/tags:$(git rev-parse refs/tags/second.2) + 1:tag:/tags:$(git rev-parse refs/tags/third) + 1:tag:/tags:$(git rev-parse refs/tags/fourth) + 1:tag:/tags:$(git rev-parse refs/tags/tree-tag) + 1:tag:/tags:$(git rev-parse refs/tags/blob-tag) + 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{}) + 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) + 3:tree::$(git rev-parse topic^{tree}) + 3:tree::$(git rev-parse base^{tree}) + 3:tree::$(git rev-parse base~1^{tree}) + 3:tree::$(git rev-parse base~2^{tree}) + 3:tree::$(git rev-parse refs/tags/tree-tag^{}) + 3:tree::$(git rev-parse refs/tags/tree-tag2^{}) + 4:blob:a:$(git rev-parse base~2:a) + 5:blob:file2:$(git rev-parse refs/tags/tree-tag2^{}:file2) + 6:tree:a/:$(git rev-parse base:a) + 7:tree:child/:$(git rev-parse refs/tags/tree-tag:child) + 8:blob:child/file:$(git rev-parse refs/tags/tree-tag:child/file) + 9:tree:left/:$(git rev-parse base:left) + 9:tree:left/:$(git rev-parse base~2:left) + 10:blob:left/b:$(git rev-parse base~2:left/b) + 10:blob:left/b:$(git rev-parse base:left/b) + 11:tree:right/:$(git rev-parse topic:right) + 11:tree:right/:$(git rev-parse base~1:right) + 11:tree:right/:$(git rev-parse base~2:right) + 12:blob:right/c:$(git rev-parse base~2:right/c) + 12:blob:right/c:$(git rev-parse topic:right/c) + 13:blob:right/d:$(git rev-parse base~1:right/d) + blobs:10 + commits:4 + tags:7 + trees:13 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'indexed objects' ' + test_when_finished git reset --hard && + + # stage change into index, adding a blob but + # also invalidating the cache-tree for the root + # and the "left" directory. + echo bogus >left/c && + git add left && + + test-tool path-walk -- --indexed-objects >out && + + cat >expect <<-EOF && + 0:blob:a:$(git rev-parse HEAD:a) + 1:blob:left/b:$(git rev-parse HEAD:left/b) + 2:blob:left/c:$(git rev-parse :left/c) + 3:blob:right/c:$(git rev-parse HEAD:right/c) + 4:blob:right/d:$(git rev-parse HEAD:right/d) + 5:tree:right/:$(git rev-parse topic:right) + blobs:5 + commits:0 + tags:0 + trees:1 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'branches and indexed objects mix well' ' + test_when_finished git reset --hard && + + # stage change into index, adding a blob but + # also invalidating the cache-tree for the root + # and the "right" directory. + echo fake >right/d && + git add right && + + test-tool path-walk -- --indexed-objects --branches >out && + + cat >expect <<-EOF && + 0:commit::$(git rev-parse topic) + 0:commit::$(git rev-parse base) + 0:commit::$(git rev-parse base~1) + 0:commit::$(git rev-parse base~2) + 1:tree::$(git rev-parse topic^{tree}) + 1:tree::$(git rev-parse base^{tree}) + 1:tree::$(git rev-parse base~1^{tree}) + 1:tree::$(git rev-parse base~2^{tree}) + 2:tree:a/:$(git rev-parse refs/tags/third:a) + 3:tree:left/:$(git rev-parse base:left) + 3:tree:left/:$(git rev-parse base~2:left) + 4:blob:left/b:$(git rev-parse base:left/b) + 4:blob:left/b:$(git rev-parse base~2:left/b) + 5:tree:right/:$(git rev-parse topic:right) + 5:tree:right/:$(git rev-parse base~1:right) + 5:tree:right/:$(git rev-parse base~2:right) + 6:blob:right/c:$(git rev-parse base~2:right/c) + 6:blob:right/c:$(git rev-parse topic:right/c) + 7:blob:right/d:$(git rev-parse base~1:right/d) + 7:blob:right/d:$(git rev-parse :right/d) + 8:blob:a:$(git rev-parse base~2:a) + blobs:7 + commits:4 + tags:0 + trees:10 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'base & topic, sparse' ' + cat >patterns <<-EOF && + /* + !/*/ + /left/ + EOF + + test-tool path-walk --stdin-pl -- base topic <patterns >out && + + cat >expect <<-EOF && + 0:commit::$(git rev-parse topic) + 0:commit::$(git rev-parse base) + 0:commit::$(git rev-parse base~1) + 0:commit::$(git rev-parse base~2) + 1:tree::$(git rev-parse topic^{tree}) + 1:tree::$(git rev-parse base^{tree}) + 1:tree::$(git rev-parse base~1^{tree}) + 1:tree::$(git rev-parse base~2^{tree}) + 2:blob:a:$(git rev-parse base~2:a) + 3:tree:left/:$(git rev-parse base:left) + 3:tree:left/:$(git rev-parse base~2:left) + 4:blob:left/b:$(git rev-parse base~2:left/b) + 4:blob:left/b:$(git rev-parse base:left/b) + blobs:3 + commits:4 + tags:0 + trees:6 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'topic only' ' + test-tool path-walk -- topic >out && + + cat >expect <<-EOF && + 0:commit::$(git rev-parse topic) + 0:commit::$(git rev-parse base~1) + 0:commit::$(git rev-parse base~2) + 1:tree::$(git rev-parse topic^{tree}) + 1:tree::$(git rev-parse base~1^{tree}) + 1:tree::$(git rev-parse base~2^{tree}) + 2:blob:a:$(git rev-parse base~2:a) + 3:tree:left/:$(git rev-parse base~2:left) + 4:blob:left/b:$(git rev-parse base~2:left/b) + 5:tree:right/:$(git rev-parse topic:right) + 5:tree:right/:$(git rev-parse base~1:right) + 5:tree:right/:$(git rev-parse base~2:right) + 6:blob:right/c:$(git rev-parse base~2:right/c) + 6:blob:right/c:$(git rev-parse topic:right/c) + 7:blob:right/d:$(git rev-parse base~1:right/d) + blobs:5 + commits:3 + tags:0 + trees:7 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'topic, not base' ' + test-tool path-walk -- topic --not base >out && + + cat >expect <<-EOF && + 0:commit::$(git rev-parse topic) + 1:tree::$(git rev-parse topic^{tree}) + 2:blob:a:$(git rev-parse topic:a):UNINTERESTING + 3:tree:left/:$(git rev-parse topic:left):UNINTERESTING + 4:blob:left/b:$(git rev-parse topic:left/b):UNINTERESTING + 5:tree:right/:$(git rev-parse topic:right) + 6:blob:right/c:$(git rev-parse topic:right/c) + 7:blob:right/d:$(git rev-parse topic:right/d):UNINTERESTING + blobs:4 + commits:1 + tags:0 + trees:3 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'fourth, blob-tag2, not base' ' + test-tool path-walk -- fourth blob-tag2 --not base >out && + + cat >expect <<-EOF && + 0:commit::$(git rev-parse topic) + 1:tag:/tags:$(git rev-parse fourth) + 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) + 3:tree::$(git rev-parse topic^{tree}) + 4:blob:a:$(git rev-parse base~1:a):UNINTERESTING + 5:tree:left/:$(git rev-parse base~1:left):UNINTERESTING + 6:blob:left/b:$(git rev-parse base~1:left/b):UNINTERESTING + 7:tree:right/:$(git rev-parse topic:right) + 8:blob:right/c:$(git rev-parse topic:right/c) + 9:blob:right/d:$(git rev-parse base~1:right/d):UNINTERESTING + blobs:5 + commits:1 + tags:1 + trees:3 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'topic, not base, only blobs' ' + test-tool path-walk --no-trees --no-commits \ + -- topic --not base >out && + + cat >expect <<-EOF && + 0:blob:a:$(git rev-parse topic:a):UNINTERESTING + 1:blob:left/b:$(git rev-parse topic:left/b):UNINTERESTING + 2:blob:right/c:$(git rev-parse topic:right/c) + 3:blob:right/d:$(git rev-parse topic:right/d):UNINTERESTING + blobs:4 + commits:0 + tags:0 + trees:0 + EOF + + test_cmp_sorted expect out +' + +# No, this doesn't make a lot of sense for the path-walk API, +# but it is possible to do. +test_expect_success 'topic, not base, only commits' ' + test-tool path-walk --no-blobs --no-trees \ + -- topic --not base >out && + + cat >expect <<-EOF && + 0:commit::$(git rev-parse topic) + commits:1 + blobs:0 + tags:0 + trees:0 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'topic, not base, only trees' ' + test-tool path-walk --no-blobs --no-commits \ + -- topic --not base >out && + + cat >expect <<-EOF && + 0:tree::$(git rev-parse topic^{tree}) + 1:tree:left/:$(git rev-parse topic:left):UNINTERESTING + 2:tree:right/:$(git rev-parse topic:right) + commits:0 + blobs:0 + tags:0 + trees:3 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'topic, not base, boundary' ' + test-tool path-walk -- --boundary topic --not base >out && + + cat >expect <<-EOF && + 0:commit::$(git rev-parse topic) + 0:commit::$(git rev-parse base~1):UNINTERESTING + 1:tree::$(git rev-parse topic^{tree}) + 1:tree::$(git rev-parse base~1^{tree}):UNINTERESTING + 2:blob:a:$(git rev-parse base~1:a):UNINTERESTING + 3:tree:left/:$(git rev-parse base~1:left):UNINTERESTING + 4:blob:left/b:$(git rev-parse base~1:left/b):UNINTERESTING + 5:tree:right/:$(git rev-parse topic:right) + 5:tree:right/:$(git rev-parse base~1:right):UNINTERESTING + 6:blob:right/c:$(git rev-parse base~1:right/c):UNINTERESTING + 6:blob:right/c:$(git rev-parse topic:right/c) + 7:blob:right/d:$(git rev-parse base~1:right/d):UNINTERESTING + blobs:5 + commits:2 + tags:0 + trees:5 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'topic, not base, boundary with pruning' ' + test-tool path-walk --prune -- --boundary topic --not base >out && + + cat >expect <<-EOF && + 0:commit::$(git rev-parse topic) + 0:commit::$(git rev-parse base~1):UNINTERESTING + 1:tree::$(git rev-parse topic^{tree}) + 1:tree::$(git rev-parse base~1^{tree}):UNINTERESTING + 2:tree:right/:$(git rev-parse topic:right) + 2:tree:right/:$(git rev-parse base~1:right):UNINTERESTING + 3:blob:right/c:$(git rev-parse base~1:right/c):UNINTERESTING + 3:blob:right/c:$(git rev-parse topic:right/c) + blobs:2 + commits:2 + tags:0 + trees:4 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'trees are reported exactly once' ' + test_when_finished "rm -rf unique-trees" && + test_create_repo unique-trees && + ( + cd unique-trees && + mkdir initial && + test_commit initial/file && + git switch -c move-to-top && + git mv initial/file.t ./ && + test_tick && + git commit -m moved && + git update-ref refs/heads/other HEAD + ) && + test-tool -C unique-trees path-walk -- --all >out && + tree=$(git -C unique-trees rev-parse HEAD:) && + grep "$tree" out >out-filtered && + test_line_count = 1 out-filtered +' + +test_done diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh index 6f526c37c2..2c147072c1 100755 --- a/t/t7030-verify-tag.sh +++ b/t/t7030-verify-tag.sh @@ -7,6 +7,13 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh . "$TEST_DIRECTORY/lib-gpg.sh" +test_expect_success GPG 'verify-tag does not crash with -h' ' + test_expect_code 129 git verify-tag -h >usage && + test_grep "[Uu]sage: git verify-tag " usage && + test_expect_code 129 nongit git verify-tag -h >usage && + test_grep "[Uu]sage: git verify-tag " usage +' + test_expect_success GPG 'create signed tags' ' echo 1 >file && git add file && test_tick && git commit -m initial && diff --git a/t/t7110-reset-merge.sh b/t/t7110-reset-merge.sh index 61669a2d21..9a335071af 100755 --- a/t/t7110-reset-merge.sh +++ b/t/t7110-reset-merge.sh @@ -270,13 +270,13 @@ test_expect_success '--merge is ok with added/deleted merge' ' git reset --hard third && rm -f file2 && test_must_fail git merge branch3 && - ! test -f file2 && - test -f file3 && + test_path_is_missing file2 && + test_path_is_file file3 && git diff --exit-code file3 && git diff --exit-code branch3 file3 && git reset --merge HEAD && - ! test -f file3 && - ! test -f file2 && + test_path_is_missing file3 && + test_path_is_missing file2 && git diff --exit-code --cached ' @@ -284,8 +284,8 @@ test_expect_success '--keep fails with added/deleted merge' ' git reset --hard third && rm -f file2 && test_must_fail git merge branch3 && - ! test -f file2 && - test -f file3 && + test_path_is_missing file2 && + test_path_is_file file3 && git diff --exit-code file3 && git diff --exit-code branch3 file3 && test_must_fail git reset --keep HEAD 2>err.log && diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 297c6c3b5c..c562bad042 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -1093,7 +1093,9 @@ test_expect_success 'submodule update --quiet passes quietness to fetch with a s ) && git clone super4 super5 && (cd super5 && - git submodule update --quiet --init --depth=1 submodule3 >out 2>err && + # This test var can mess with the stderr output checked in this test. + GIT_TEST_NAME_HASH_VERSION=1 \ + git submodule update --quiet --init --depth=1 submodule3 >out 2>err && test_must_be_empty out && test_must_be_empty err ) && diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh index 8d7b234beb..77b6d0040e 100755 --- a/t/t7407-submodule-foreach.sh +++ b/t/t7407-submodule-foreach.sh @@ -426,14 +426,14 @@ test_expect_success 'option-like arguments passed to foreach commands are not lo git submodule foreach "echo be --quiet" > ../expected && git submodule foreach echo be --quiet > ../actual ) && - grep -sq -e "--quiet" expected && + test_grep -e "--quiet" expected && test_cmp expected actual ' test_expect_success 'option-like arguments passed to foreach recurse correctly' ' git -C clone2 submodule foreach --recursive "echo be --an-option" >expect && git -C clone2 submodule foreach --recursive echo be --an-option >actual && - grep -e "--an-option" expect && + test_grep -e "--an-option" expect && test_cmp expect actual ' diff --git a/t/t7422-submodule-output.sh b/t/t7422-submodule-output.sh index f21e920367..023a5cbdc4 100755 --- a/t/t7422-submodule-output.sh +++ b/t/t7422-submodule-output.sh @@ -167,10 +167,45 @@ do done test_expect_success !MINGW 'git submodule status --recursive propagates SIGPIPE' ' - { git submodule status --recursive 2>err; echo $?>status; } | - grep -q X/S && - test_must_be_empty err && - test_match_signal 13 "$(cat status)" + # The test setup is somewhat involved because triggering a SIGPIPE is + # racy with buffered pipes. To avoid the raciness we thus need to make + # sure that the subprocess in question fills the buffers completely, + # which requires a couple thousand submodules in total. + test_when_finished "rm -rf submodule repo" && + git init submodule && + ( + cd submodule && + test_commit initial && + + COMMIT=$(git rev-parse HEAD) && + for i in $(test_seq 2000) + do + printf "[submodule \"sm-$i\"]\npath = recursive-submodule-path-$i\n" "$i" || + return 1 + done >gitmodules && + BLOB=$(git hash-object -w --stdin <gitmodules) && + + printf "100644 blob $BLOB\t.gitmodules\n" >tree && + for i in $(test_seq 2000) + do + printf "160000 commit $COMMIT\trecursive-submodule-path-%d\n" "$i" || + return 1 + done >>tree && + TREE=$(git mktree <tree) && + + COMMIT=$(git commit-tree "$TREE") && + git reset --hard "$COMMIT" + ) && + + git init repo && + ( + cd repo && + GIT_ALLOW_PROTOCOL=file git submodule add "$(pwd)"/../submodule && + { git submodule status --recursive 2>err; echo $?>status; } | + grep -q recursive-submodule-path-1 && + test_must_be_empty err && + test_match_signal 13 "$(cat status)" + ) ' test_done diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh index 0d2dd29fe6..39677e859a 100755 --- a/t/t7510-signed-commit.sh +++ b/t/t7510-signed-commit.sh @@ -8,6 +8,13 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME GNUPGHOME_NOT_USED=$GNUPGHOME . "$TEST_DIRECTORY/lib-gpg.sh" +test_expect_success GPG 'verify-commit does not crash with -h' ' + test_expect_code 129 git verify-commit -h >usage && + test_grep "[Uu]sage: git verify-commit " usage && + test_expect_code 129 nongit git verify-commit -h >usage && + test_grep "[Uu]sage: git verify-commit " usage +' + test_expect_success GPG 'create signed commits' ' test_oid_cache <<-\EOF && header sha1:gpgsig diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index ef54cff4fa..2a8df29219 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -173,7 +173,7 @@ test_expect_success 'merge -h with invalid index' ' cd broken && git init && >.git/index && - test_expect_code 129 git merge -h 2>usage + test_expect_code 129 git merge -h >usage ) && test_grep "[Uu]sage: git merge" broken/usage ' diff --git a/t/t7603-merge-reduce-heads.sh b/t/t7603-merge-reduce-heads.sh index 4887ca705b..1f8c3b7ccb 100755 --- a/t/t7603-merge-reduce-heads.sh +++ b/t/t7603-merge-reduce-heads.sh @@ -52,12 +52,12 @@ test_expect_success 'merge c1 with c2, c3, c4, c5' ' test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" && test "$(git rev-parse c5)" = "$(git rev-parse HEAD^4)" && git diff --exit-code && - test -f c0.c && - test -f c1.c && - test -f c2.c && - test -f c3.c && - test -f c4.c && - test -f c5.c && + test_path_is_file c0.c && + test_path_is_file c1.c && + test_path_is_file c2.c && + test_path_is_file c3.c && + test_path_is_file c4.c && + test_path_is_file c5.c && git show --format=%s -s >actual && ! grep c1 actual && grep c2 actual && @@ -75,12 +75,12 @@ test_expect_success 'pull c2, c3, c4, c5 into c1' ' test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" && test "$(git rev-parse c5)" = "$(git rev-parse HEAD^4)" && git diff --exit-code && - test -f c0.c && - test -f c1.c && - test -f c2.c && - test -f c3.c && - test -f c4.c && - test -f c5.c && + test_path_is_file c0.c && + test_path_is_file c1.c && + test_path_is_file c2.c && + test_path_is_file c3.c && + test_path_is_file c4.c && + test_path_is_file c5.c && git show --format=%s -s >actual && ! grep c1 actual && grep c2 actual && diff --git a/t/t7609-mergetool--lib.sh b/t/t7609-mergetool--lib.sh index e8e205707e..af3ad284ee 100755 --- a/t/t7609-mergetool--lib.sh +++ b/t/t7609-mergetool--lib.sh @@ -7,7 +7,7 @@ Testing basic merge tools options' . ./test-lib.sh test_expect_success 'mergetool --tool=vimdiff creates the expected layout' ' - . "$GIT_TEST_MERGE_TOOLS_DIR"/vimdiff && + . "$GIT_SOURCE_DIR"/mergetools/vimdiff && run_unit_tests ' diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index be1188e736..611755cc13 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -308,7 +308,10 @@ test_expect_success 'no bitmaps created if .keep files present' ' keep=${pack%.pack}.keep && test_when_finished "rm -f \"\$keep\"" && >"$keep" && - git -C bare.git repack -ad 2>stderr && + + # Disable --name-hash-version test due to stderr comparison. + GIT_TEST_NAME_HASH_VERSION=1 \ + git -C bare.git repack -ad 2>stderr && test_must_be_empty stderr && find bare.git/objects/pack/ -type f -name "*.bitmap" >actual && test_must_be_empty actual @@ -319,7 +322,10 @@ test_expect_success 'auto-bitmaps do not complain if unavailable' ' blob=$(test-tool genrandom big $((1024*1024)) | git -C bare.git hash-object -w --stdin) && git -C bare.git update-ref refs/tags/big $blob && - git -C bare.git repack -ad 2>stderr && + + # Disable --name-hash-version test due to stderr comparison. + GIT_TEST_NAME_HASH_VERSION=1 \ + git -C bare.git repack -ad 2>stderr && test_must_be_empty stderr && find bare.git/objects/pack -type f -name "*.bitmap" >actual && test_must_be_empty actual @@ -776,6 +782,12 @@ test_expect_success 'repack -ad cleans up old .tmp-* packs' ' test_must_be_empty tmpfiles ' +test_expect_success '--name-hash-version option passes through to pack-objects' ' + GIT_TRACE2_EVENT="$(pwd)/hash-trace.txt" \ + git repack -a --name-hash-version=2 && + test_subcommand_flex git pack-objects --name-hash-version=2 <hash-trace.txt +' + test_expect_success 'setup for update-server-info' ' git init update-server-info && test_commit -C update-server-info message diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh index 5715f4d69a..5559d4ccb4 100755 --- a/t/t7701-repack-unpack-unreachable.sh +++ b/t/t7701-repack-unpack-unreachable.sh @@ -195,4 +195,20 @@ test_expect_success 'repack -k packs unreachable loose objects' ' git cat-file -p $sha1 ' +test_expect_success 'repack -k packs unreachable loose objects without existing packfiles' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + oid=$(echo would-be-deleted-loose | git hash-object -w --stdin) && + objpath=.git/objects/$(echo $sha1 | sed "s,..,&/,") && + test_path_is_file $objpath && + + git repack -ad --keep-unreachable && + test_path_is_missing $objpath && + git cat-file -p $oid + ) +' + test_done diff --git a/t/t7704-repack-cruft.sh b/t/t7704-repack-cruft.sh index 959e6e2648..43d2947d28 100755 --- a/t/t7704-repack-cruft.sh +++ b/t/t7704-repack-cruft.sh @@ -304,6 +304,72 @@ test_expect_success '--max-cruft-size with freshened objects (packed)' ' ) ' +test_expect_success '--max-cruft-size with freshened objects (previously cruft)' ' + repo="max-cruft-size-threshold" && + + test_when_finished "rm -fr $repo" && + git init "$repo" && + ( + cd "$repo" && + + test_commit base && + foo="$(generate_random_blob foo $((2*1024*1024)))" && + bar="$(generate_random_blob bar $((2*1024*1024)))" && + baz="$(generate_random_blob baz $((2*1024*1024)))" && + + test-tool chmtime --get -100000 \ + "$objdir/$(test_oid_to_path "$foo")" >foo.old && + test-tool chmtime --get -100000 \ + "$objdir/$(test_oid_to_path "$bar")" >bar.old && + test-tool chmtime --get -100000 \ + "$objdir/$(test_oid_to_path "$baz")" >baz.old && + + git repack --cruft -d && + + # Make an identical copy of foo stored in a pack with a more + # recent mtime. + foo="$(generate_random_blob foo $((2*1024*1024)))" && + foo_pack="$(echo "$foo" | git pack-objects $packdir/pack)" && + test-tool chmtime --get -100 \ + "$packdir/pack-$foo_pack.pack" >foo.new && + git prune-packed && + + # Make a loose copy of bar, also with a more recent mtime. + bar="$(generate_random_blob bar $((2*1024*1024)))" && + test-tool chmtime --get -100 \ + "$objdir/$(test_oid_to_path "$bar")" >bar.new && + + # Make a new cruft object $quux to ensure we do not + # generate an identical pack to the existing cruft + # pack. + quux="$(generate_random_blob quux $((1024)))" && + test-tool chmtime --get -100 \ + "$objdir/$(test_oid_to_path "$quux")" >quux.new && + + git repack --cruft --max-cruft-size=3M -d && + + for p in $packdir/pack-*.mtimes + do + test-tool pack-mtimes "$(basename "$p")" || return 1 + done >actual.raw && + sort actual.raw >actual && + + # Among the set of all cruft packs, we should see both + # mtimes for object $foo and $bar, as well as the + # single new copy of $baz. + sort >expect <<-EOF && + $foo $(cat foo.old) + $foo $(cat foo.new) + $bar $(cat bar.old) + $bar $(cat bar.new) + $baz $(cat baz.old) + $quux $(cat quux.new) + EOF + + test_cmp expect actual + ) +' + test_expect_success '--max-cruft-size with pruning' ' git init max-cruft-size-prune && ( diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh index 1ad039e123..e98993276a 100755 --- a/t/t8002-blame.sh +++ b/t/t8002-blame.sh @@ -138,7 +138,7 @@ test_expect_success 'blame --abbrev -b truncates the blank boundary' ' # Note that `--abbrev=` always gets incremented by 1, which is why we # expect 11 leading spaces and not 10. cat >expect <<-EOF && - $(printf "%0.s " $(test_seq 11)) (<author@example.com> 2005-04-07 15:45:13 -0700 1) abbrev + $(printf "%11s" "") (<author@example.com> 2005-04-07 15:45:13 -0700 1) abbrev EOF git blame -b --abbrev=10 ^HEAD -- abbrev.t >actual && test_cmp expect actual @@ -146,7 +146,7 @@ test_expect_success 'blame --abbrev -b truncates the blank boundary' ' test_expect_success 'blame with excessive --abbrev and -b culls to hash length' ' cat >expect <<-EOF && - $(printf "%0.s " $(test_seq $hexsz)) (<author@example.com> 2005-04-07 15:45:13 -0700 1) abbrev + $(printf "%${hexsz}s" "") (<author@example.com> 2005-04-07 15:45:13 -0700 1) abbrev EOF git blame -b --abbrev=9000 ^HEAD -- abbrev.t >actual && test_cmp expect actual diff --git a/t/t9003-help-autocorrect.sh b/t/t9003-help-autocorrect.sh index 85a5074b5e..8da318d2b5 100755 --- a/t/t9003-help-autocorrect.sh +++ b/t/t9003-help-autocorrect.sh @@ -28,15 +28,18 @@ test_expect_success 'setup' ' test_cmp expect actual ' -test_expect_success 'autocorrect showing candidates' ' - git config help.autocorrect 0 && +for show in false no off 0 show +do + test_expect_success 'autocorrect showing candidates' ' + git config help.autocorrect $show && - test_must_fail git lfg 2>actual && - grep "^ lgf" actual && + test_must_fail git lfg 2>actual && + grep "^ lgf" actual && - test_must_fail git distimdist 2>actual && - grep "^ distimdistim" actual -' + test_must_fail git distimdist 2>actual && + grep "^ distimdistim" actual + ' +done for immediate in -1 immediate do diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 40427883ec..304bac5b1d 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -8,6 +8,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh +. "$TEST_DIRECTORY/lib-gpg.sh" test_expect_success 'setup' ' @@ -253,6 +254,24 @@ test_expect_success 'signed-tags=verbatim' ' ' +test_expect_success 'signed-tags=warn-verbatim' ' + + git fast-export --signed-tags=warn-verbatim sign-your-name >output 2>err && + grep PGP output && + test -s err + +' + +# 'warn' is a backward-compatibility alias for 'warn-verbatim'; test +# that it keeps working. +test_expect_success 'signed-tags=warn' ' + + git fast-export --signed-tags=warn sign-your-name >output 2>err && + grep PGP output && + test -s err + +' + test_expect_success 'signed-tags=strip' ' git fast-export --signed-tags=strip sign-your-name > output && @@ -266,10 +285,107 @@ test_expect_success 'signed-tags=warn-strip' ' test -s err ' +test_expect_success GPG 'set up signed commit' ' + + # Generate a commit with both "gpgsig" and "encoding" set, so + # that we can test that fast-import gets the ordering correct + # between the two. + test_config i18n.commitEncoding ISO-8859-1 && + git checkout -f -b commit-signing main && + echo Sign your name >file-sign && + git add file-sign && + git commit -S -m "signed commit" && + COMMIT_SIGNING=$(git rev-parse --verify commit-signing) + +' + +test_expect_success GPG 'signed-commits default' ' + + sane_unset FAST_EXPORT_SIGNED_COMMITS_NOABORT && + test_must_fail git fast-export --reencode=no commit-signing && + + FAST_EXPORT_SIGNED_COMMITS_NOABORT=1 git fast-export --reencode=no commit-signing >output 2>err && + ! grep ^gpgsig output && + grep "^encoding ISO-8859-1" output && + test -s err && + sed "s/commit-signing/commit-strip-signing/" output | ( + cd new && + git fast-import && + STRIPPED=$(git rev-parse --verify refs/heads/commit-strip-signing) && + test $COMMIT_SIGNING != $STRIPPED + ) + +' + +test_expect_success GPG 'signed-commits=abort' ' + + test_must_fail git fast-export --signed-commits=abort commit-signing + +' + +test_expect_success GPG 'signed-commits=verbatim' ' + + git fast-export --signed-commits=verbatim --reencode=no commit-signing >output && + grep "^gpgsig sha" output && + grep "encoding ISO-8859-1" output && + ( + cd new && + git fast-import && + STRIPPED=$(git rev-parse --verify refs/heads/commit-signing) && + test $COMMIT_SIGNING = $STRIPPED + ) <output + +' + +test_expect_success GPG 'signed-commits=warn-verbatim' ' + + git fast-export --signed-commits=warn-verbatim --reencode=no commit-signing >output 2>err && + grep "^gpgsig sha" output && + grep "encoding ISO-8859-1" output && + test -s err && + ( + cd new && + git fast-import && + STRIPPED=$(git rev-parse --verify refs/heads/commit-signing) && + test $COMMIT_SIGNING = $STRIPPED + ) <output + +' + +test_expect_success GPG 'signed-commits=strip' ' + + git fast-export --signed-commits=strip --reencode=no commit-signing >output && + ! grep ^gpgsig output && + grep "^encoding ISO-8859-1" output && + sed "s/commit-signing/commit-strip-signing/" output | ( + cd new && + git fast-import && + STRIPPED=$(git rev-parse --verify refs/heads/commit-strip-signing) && + test $COMMIT_SIGNING != $STRIPPED + ) + +' + +test_expect_success GPG 'signed-commits=warn-strip' ' + + git fast-export --signed-commits=warn-strip --reencode=no commit-signing >output 2>err && + ! grep ^gpgsig output && + grep "^encoding ISO-8859-1" output && + test -s err && + sed "s/commit-signing/commit-strip-signing/" output | ( + cd new && + git fast-import && + STRIPPED=$(git rev-parse --verify refs/heads/commit-strip-signing) && + test $COMMIT_SIGNING != $STRIPPED + ) + +' + test_expect_success 'setup submodule' ' test_config_global protocol.file.allow always && git checkout -f main && + test_might_fail git update-ref -d refs/heads/commit-signing && mkdir sub && ( cd sub && diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 78e054ab50..79377bc0fc 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -927,7 +927,7 @@ test_expect_success () { test -n "$test_skip_test_preamble" || say >&3 "expecting success of $TEST_NUMBER.$test_count '$1': $test_body" if test_run_ "$test_body" && - check_test_results_san_file_empty_ + ! check_test_results_san_file_has_entries_ then test_ok_ "$1" else @@ -1268,6 +1268,16 @@ test_cmp () { eval "$GIT_TEST_CMP" '"$@"' } +# test_cmp_sorted runs test_cmp on sorted versions of the two +# input files. Uses "$1.sorted" and "$2.sorted" as temp files. + +test_cmp_sorted () { + sort <"$1" >"$1.sorted" && + sort <"$2" >"$2.sorted" && + test_cmp "$1.sorted" "$2.sorted" && + rm "$1.sorted" "$2.sorted" +} + # Check that the given config key has the expected value. # # test_cmp_config [-C <dir>] <expected-value> @@ -1886,6 +1896,32 @@ test_subcommand () { fi } +# Check that the given subcommand was run with the given set of +# arguments in order (but with possible extra arguments). +# +# test_subcommand_flex [!] <command> <args>... < <trace> +# +# If the first parameter passed is !, this instead checks that +# the given command was not called. +# +test_subcommand_flex () { + local negate= + if test "$1" = "!" + then + negate=t + shift + fi + + local expr="$(printf '"%s".*' "$@")" + + if test -n "$negate" + then + ! grep "\[$expr\]" + else + grep "\[$expr\]" + fi +} + # Check that the given command was invoked as part of the # trace2-format trace on stdin. # @@ -2007,3 +2043,11 @@ test_trailing_hash () { test-tool hexdump | sed "s/ //g" } + +# Trim and replace each character with ascii code below 32 or above +# 127 (included) using a dot '.' character. +# Octal intervals \001-\040 and \177-\377 +# correspond to decimal intervals 1-32 and 127-255 +test_redact_non_printables () { + tr -d "\n\r" | tr "[\001-\040][\177-\377]" "." +} diff --git a/t/test-lib.sh b/t/test-lib.sh index d1f62adbf8..9001ed3a64 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1169,20 +1169,20 @@ test_atexit_handler () { teardown_malloc_check } -check_test_results_san_file_empty_ () { - test -z "$TEST_RESULTS_SAN_FILE" && return 0 - - # stderr piped to /dev/null because the directory may have - # been "rmdir"'d already. - ! find "$TEST_RESULTS_SAN_DIR" \ - -type f \ - -name "$TEST_RESULTS_SAN_FILE_PFX.*" 2>/dev/null | - xargs grep ^DEDUP_TOKEN | +check_test_results_san_file_has_entries_ () { + test -z "$TEST_RESULTS_SAN_FILE" && return 1 + + # Lines marked with DEDUP_TOKEN show unique leaks. We only care that we + # found at least one. + # + # But also suppress any false positives caused by bugs or races in the + # sanitizer itself. + grep -s ^DEDUP_TOKEN "$TEST_RESULTS_SAN_FILE".* | grep -qv sanitizer::GetThreadStackTopAndBottom } check_test_results_san_file_ () { - if check_test_results_san_file_empty_ + if ! check_test_results_san_file_has_entries_ then return fi && @@ -1862,6 +1862,10 @@ test_lazy_prereq CURL ' curl --version ' +test_lazy_prereq WITHOUT_BREAKING_CHANGES ' + test -z "$WITH_BREAKING_CHANGES" +' + # SHA1 is a test if the hash algorithm in use is SHA-1. This is both for tests # which will not work with other hash algorithms and tests that work but don't # test anything meaningful (e.g. special values which cause short collisions). diff --git a/t/unit-tests/generate-clar-decls.sh b/t/unit-tests/generate-clar-decls.sh index 3b315c64b3..abf6a2ea2a 100755 --- a/t/unit-tests/generate-clar-decls.sh +++ b/t/unit-tests/generate-clar-decls.sh @@ -14,6 +14,7 @@ do suite_name=$(basename "$suite") suite_name=${suite_name%.c} suite_name=${suite_name#u-} + suite_name=$(echo "$suite_name" | tr '-' '_') sed -ne "s/^\(void test_${suite_name}__[a-zA-Z_0-9][a-zA-Z_0-9]*(void)\)$/extern \1;/p" "$suite" || exit 1 done >"$OUTPUT" diff --git a/t/unit-tests/lib-oid.c b/t/unit-tests/lib-oid.c index 8f0ccac532..e0b3180f23 100644 --- a/t/unit-tests/lib-oid.c +++ b/t/unit-tests/lib-oid.c @@ -1,9 +1,9 @@ -#include "test-lib.h" +#include "unit-test.h" #include "lib-oid.h" #include "strbuf.h" #include "hex.h" -int init_hash_algo(void) +int cl_setup_hash_algo(void) { static int algo = -1; @@ -11,42 +11,32 @@ int init_hash_algo(void) const char *algo_name = getenv("GIT_TEST_DEFAULT_HASH"); algo = algo_name ? hash_algo_by_name(algo_name) : GIT_HASH_SHA1; - if (!check(algo != GIT_HASH_UNKNOWN)) - test_msg("BUG: invalid GIT_TEST_DEFAULT_HASH value ('%s')", - algo_name); + cl_assert(algo != GIT_HASH_UNKNOWN); } return algo; } -static int get_oid_arbitrary_hex_algop(const char *hex, struct object_id *oid, +static void cl_parse_oid(const char *hex, struct object_id *oid, const struct git_hash_algo *algop) { - int ret; size_t sz = strlen(hex); struct strbuf buf = STRBUF_INIT; - if (!check(sz <= algop->hexsz)) { - test_msg("BUG: hex string (%s) bigger than maximum allowed (%lu)", - hex, (unsigned long)algop->hexsz); - return -1; - } + cl_assert(sz <= algop->hexsz); strbuf_add(&buf, hex, sz); strbuf_addchars(&buf, '0', algop->hexsz - sz); - ret = get_oid_hex_algop(buf.buf, oid, algop); - if (!check_int(ret, ==, 0)) - test_msg("BUG: invalid hex input (%s) provided", hex); + cl_assert_equal_i(get_oid_hex_algop(buf.buf, oid, algop), 0); strbuf_release(&buf); - return ret; } -int get_oid_arbitrary_hex(const char *hex, struct object_id *oid) + +void cl_parse_any_oid(const char *hex, struct object_id *oid) { - int hash_algo = init_hash_algo(); + int hash_algo = cl_setup_hash_algo(); - if (!check_int(hash_algo, !=, GIT_HASH_UNKNOWN)) - return -1; - return get_oid_arbitrary_hex_algop(hex, oid, &hash_algos[hash_algo]); + cl_assert(hash_algo != GIT_HASH_UNKNOWN); + cl_parse_oid(hex, oid, &hash_algos[hash_algo]); } diff --git a/t/unit-tests/lib-oid.h b/t/unit-tests/lib-oid.h index 4e77c04bd2..4031775104 100644 --- a/t/unit-tests/lib-oid.h +++ b/t/unit-tests/lib-oid.h @@ -5,6 +5,7 @@ /* * Convert arbitrary hex string to object_id. + * * For example, passing "abc12" will generate * "abc1200000000000000000000000000000000000" hex of length 40 for SHA-1 and * create object_id with that. @@ -12,14 +13,16 @@ * algo is not allowed. The hash algo is decided based on GIT_TEST_DEFAULT_HASH * environment variable. */ -int get_oid_arbitrary_hex(const char *s, struct object_id *oid); + +void cl_parse_any_oid (const char *s, struct object_id *oid); /* * Returns one of GIT_HASH_{SHA1, SHA256, UNKNOWN} based on the value of * GIT_TEST_DEFAULT_HASH environment variable. The fallback value in the * absence of GIT_TEST_DEFAULT_HASH is GIT_HASH_SHA1. It also uses - * check(algo != GIT_HASH_UNKNOWN) before returning to verify if the + * cl_assert(algo != GIT_HASH_UNKNOWN) before returning to verify if the * GIT_TEST_DEFAULT_HASH's value is valid or not. */ -int init_hash_algo(void); + +int cl_setup_hash_algo(void); #endif /* LIB_OID_H */ diff --git a/t/unit-tests/t-example-decorate.c b/t/unit-tests/t-example-decorate.c deleted file mode 100644 index bfc776e223..0000000000 --- a/t/unit-tests/t-example-decorate.c +++ /dev/null @@ -1,74 +0,0 @@ -#define USE_THE_REPOSITORY_VARIABLE - -#include "test-lib.h" -#include "object.h" -#include "decorate.h" -#include "repository.h" - -struct test_vars { - struct object *one, *two, *three; - struct decoration n; - int decoration_a, decoration_b; -}; - -static void t_add(struct test_vars *vars) -{ - void *ret = add_decoration(&vars->n, vars->one, &vars->decoration_a); - - check(ret == NULL); - ret = add_decoration(&vars->n, vars->two, NULL); - check(ret == NULL); -} - -static void t_readd(struct test_vars *vars) -{ - void *ret = add_decoration(&vars->n, vars->one, NULL); - - check(ret == &vars->decoration_a); - ret = add_decoration(&vars->n, vars->two, &vars->decoration_b); - check(ret == NULL); -} - -static void t_lookup(struct test_vars *vars) -{ - void *ret = lookup_decoration(&vars->n, vars->one); - - check(ret == NULL); - ret = lookup_decoration(&vars->n, vars->two); - check(ret == &vars->decoration_b); - ret = lookup_decoration(&vars->n, vars->three); - check(ret == NULL); -} - -static void t_loop(struct test_vars *vars) -{ - int objects_noticed = 0; - - for (size_t i = 0; i < vars->n.size; i++) { - if (vars->n.entries[i].base) - objects_noticed++; - } - check_int(objects_noticed, ==, 2); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - struct object_id one_oid = { { 1 } }, two_oid = { { 2 } }, three_oid = { { 3 } }; - struct test_vars vars = { 0 }; - - vars.one = lookup_unknown_object(the_repository, &one_oid); - vars.two = lookup_unknown_object(the_repository, &two_oid); - vars.three = lookup_unknown_object(the_repository, &three_oid); - - TEST(t_add(&vars), - "Add 2 objects, one with a non-NULL decoration and one with a NULL decoration."); - TEST(t_readd(&vars), - "When re-adding an already existing object, the old decoration is returned."); - TEST(t_lookup(&vars), - "Lookup returns the added declarations, or NULL if the object was never added."); - TEST(t_loop(&vars), "The user can also loop through all entries."); - - clear_decoration(&vars.n, NULL); - - return test_done(); -} diff --git a/t/unit-tests/t-mem-pool.c b/t/unit-tests/t-mem-pool.c deleted file mode 100644 index fe500c704b..0000000000 --- a/t/unit-tests/t-mem-pool.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "test-lib.h" -#include "mem-pool.h" - -static void setup_static(void (*f)(struct mem_pool *), size_t block_alloc) -{ - struct mem_pool pool = { .block_alloc = block_alloc }; - f(&pool); - mem_pool_discard(&pool, 0); -} - -static void t_calloc_100(struct mem_pool *pool) -{ - size_t size = 100; - char *buffer = mem_pool_calloc(pool, 1, size); - for (size_t i = 0; i < size; i++) - check_int(buffer[i], ==, 0); - if (!check(pool->mp_block != NULL)) - return; - check(pool->mp_block->next_free != NULL); - check(pool->mp_block->end != NULL); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST(setup_static(t_calloc_100, 1024 * 1024), - "mem_pool_calloc returns 100 zeroed bytes with big block"); - TEST(setup_static(t_calloc_100, 1), - "mem_pool_calloc returns 100 zeroed bytes with tiny block"); - - return test_done(); -} diff --git a/t/unit-tests/t-oid-array.c b/t/unit-tests/t-oid-array.c deleted file mode 100644 index 45b59a2a51..0000000000 --- a/t/unit-tests/t-oid-array.c +++ /dev/null @@ -1,126 +0,0 @@ -#define USE_THE_REPOSITORY_VARIABLE - -#include "test-lib.h" -#include "lib-oid.h" -#include "oid-array.h" -#include "hex.h" - -static int fill_array(struct oid_array *array, const char *hexes[], size_t n) -{ - for (size_t i = 0; i < n; i++) { - struct object_id oid; - - if (!check_int(get_oid_arbitrary_hex(hexes[i], &oid), ==, 0)) - return -1; - oid_array_append(array, &oid); - } - if (!check_uint(array->nr, ==, n)) - return -1; - return 0; -} - -static int add_to_oid_array(const struct object_id *oid, void *data) -{ - struct oid_array *array = data; - - oid_array_append(array, oid); - return 0; -} - -static void t_enumeration(const char **input_args, size_t input_sz, - const char **expect_args, size_t expect_sz) -{ - struct oid_array input = OID_ARRAY_INIT, expect = OID_ARRAY_INIT, - actual = OID_ARRAY_INIT; - size_t i; - - if (fill_array(&input, input_args, input_sz)) - return; - if (fill_array(&expect, expect_args, expect_sz)) - return; - - oid_array_for_each_unique(&input, add_to_oid_array, &actual); - if (!check_uint(actual.nr, ==, expect.nr)) - return; - - for (i = 0; i < actual.nr; i++) { - if (!check(oideq(&actual.oid[i], &expect.oid[i]))) - test_msg("expected: %s\n got: %s\n index: %" PRIuMAX, - oid_to_hex(&expect.oid[i]), oid_to_hex(&actual.oid[i]), - (uintmax_t)i); - } - - oid_array_clear(&actual); - oid_array_clear(&input); - oid_array_clear(&expect); -} - -#define TEST_ENUMERATION(input, expect, desc) \ - TEST(t_enumeration(input, ARRAY_SIZE(input), expect, ARRAY_SIZE(expect)), \ - desc " works") - -static void t_lookup(const char **input_hexes, size_t n, const char *query_hex, - int lower_bound, int upper_bound) -{ - struct oid_array array = OID_ARRAY_INIT; - struct object_id oid_query; - int ret; - - if (!check_int(get_oid_arbitrary_hex(query_hex, &oid_query), ==, 0)) - return; - if (fill_array(&array, input_hexes, n)) - return; - ret = oid_array_lookup(&array, &oid_query); - - if (!check_int(ret, <=, upper_bound) || - !check_int(ret, >=, lower_bound)) - test_msg("oid query for lookup: %s", oid_to_hex(&oid_query)); - - oid_array_clear(&array); -} - -#define TEST_LOOKUP(input_hexes, query, lower_bound, upper_bound, desc) \ - TEST(t_lookup(input_hexes, ARRAY_SIZE(input_hexes), query, \ - lower_bound, upper_bound), \ - desc " works") - -static void setup(void) -{ - /* The hash algo is used by oid_array_lookup() internally */ - int algo = init_hash_algo(); - if (check_int(algo, !=, GIT_HASH_UNKNOWN)) - repo_set_hash_algo(the_repository, algo); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - const char *arr_input[] = { "88", "44", "aa", "55" }; - const char *arr_input_dup[] = { "88", "44", "aa", "55", - "88", "44", "aa", "55", - "88", "44", "aa", "55" }; - const char *res_sorted[] = { "44", "55", "88", "aa" }; - const char *nearly_55; - - if (!TEST(setup(), "setup")) - test_skip_all("hash algo initialization failed"); - - TEST_ENUMERATION(arr_input, res_sorted, "ordered enumeration"); - TEST_ENUMERATION(arr_input_dup, res_sorted, - "ordered enumeration with duplicate suppression"); - - TEST_LOOKUP(arr_input, "55", 1, 1, "lookup"); - TEST_LOOKUP(arr_input, "33", INT_MIN, -1, "lookup non-existent entry"); - TEST_LOOKUP(arr_input_dup, "55", 3, 5, "lookup with duplicates"); - TEST_LOOKUP(arr_input_dup, "66", INT_MIN, -1, - "lookup non-existent entry with duplicates"); - - nearly_55 = init_hash_algo() == GIT_HASH_SHA1 ? - "5500000000000000000000000000000000000001" : - "5500000000000000000000000000000000000000000000000000000000000001"; - TEST_LOOKUP(((const char *[]){ "55", nearly_55 }), "55", 0, 0, - "lookup with almost duplicate values"); - TEST_LOOKUP(((const char *[]){ "55", "55" }), "55", 0, 1, - "lookup with single duplicate value"); - - return test_done(); -} diff --git a/t/unit-tests/t-oidmap.c b/t/unit-tests/t-oidmap.c deleted file mode 100644 index b22e52d08b..0000000000 --- a/t/unit-tests/t-oidmap.c +++ /dev/null @@ -1,181 +0,0 @@ -#include "test-lib.h" -#include "lib-oid.h" -#include "oidmap.h" -#include "hash.h" -#include "hex.h" - -/* - * Elements we will put in oidmap structs are made of a key: the entry.oid - * field, which is of type struct object_id, and a value: the name field (could - * be a refname for example). - */ -struct test_entry { - struct oidmap_entry entry; - char name[FLEX_ARRAY]; -}; - -static const char *const key_val[][2] = { { "11", "one" }, - { "22", "two" }, - { "33", "three" } }; - -static void setup(void (*f)(struct oidmap *map)) -{ - struct oidmap map = OIDMAP_INIT; - int ret = 0; - - for (size_t i = 0; i < ARRAY_SIZE(key_val); i++){ - struct test_entry *entry; - - FLEX_ALLOC_STR(entry, name, key_val[i][1]); - if ((ret = get_oid_arbitrary_hex(key_val[i][0], &entry->entry.oid))) { - free(entry); - break; - } - entry = oidmap_put(&map, entry); - if (!check(entry == NULL)) - free(entry); - } - - if (!ret) - f(&map); - oidmap_free(&map, 1); -} - -static void t_replace(struct oidmap *map) -{ - struct test_entry *entry, *prev; - - FLEX_ALLOC_STR(entry, name, "un"); - if (get_oid_arbitrary_hex("11", &entry->entry.oid)) - return; - prev = oidmap_put(map, entry); - if (!check(prev != NULL)) - return; - check_str(prev->name, "one"); - free(prev); - - FLEX_ALLOC_STR(entry, name, "deux"); - if (get_oid_arbitrary_hex("22", &entry->entry.oid)) - return; - prev = oidmap_put(map, entry); - if (!check(prev != NULL)) - return; - check_str(prev->name, "two"); - free(prev); -} - -static void t_get(struct oidmap *map) -{ - struct test_entry *entry; - struct object_id oid; - - if (get_oid_arbitrary_hex("22", &oid)) - return; - entry = oidmap_get(map, &oid); - if (!check(entry != NULL)) - return; - check_str(entry->name, "two"); - - if (get_oid_arbitrary_hex("44", &oid)) - return; - check(oidmap_get(map, &oid) == NULL); - - if (get_oid_arbitrary_hex("11", &oid)) - return; - entry = oidmap_get(map, &oid); - if (!check(entry != NULL)) - return; - check_str(entry->name, "one"); -} - -static void t_remove(struct oidmap *map) -{ - struct test_entry *entry; - struct object_id oid; - - if (get_oid_arbitrary_hex("11", &oid)) - return; - entry = oidmap_remove(map, &oid); - if (!check(entry != NULL)) - return; - check_str(entry->name, "one"); - check(oidmap_get(map, &oid) == NULL); - free(entry); - - if (get_oid_arbitrary_hex("22", &oid)) - return; - entry = oidmap_remove(map, &oid); - if (!check(entry != NULL)) - return; - check_str(entry->name, "two"); - check(oidmap_get(map, &oid) == NULL); - free(entry); - - if (get_oid_arbitrary_hex("44", &oid)) - return; - check(oidmap_remove(map, &oid) == NULL); -} - -static int key_val_contains(struct test_entry *entry, char seen[]) -{ - for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { - struct object_id oid; - - if (get_oid_arbitrary_hex(key_val[i][0], &oid)) - return -1; - - if (oideq(&entry->entry.oid, &oid)) { - if (seen[i]) - return 2; - seen[i] = 1; - return 0; - } - } - return 1; -} - -static void t_iterate(struct oidmap *map) -{ - struct oidmap_iter iter; - struct test_entry *entry; - char seen[ARRAY_SIZE(key_val)] = { 0 }; - int count = 0; - - oidmap_iter_init(map, &iter); - while ((entry = oidmap_iter_next(&iter))) { - int ret; - if (!check_int((ret = key_val_contains(entry, seen)), ==, 0)) { - switch (ret) { - case -1: - break; /* error message handled by get_oid_arbitrary_hex() */ - case 1: - test_msg("obtained entry was not given in the input\n" - " name: %s\n oid: %s\n", - entry->name, oid_to_hex(&entry->entry.oid)); - break; - case 2: - test_msg("duplicate entry detected\n" - " name: %s\n oid: %s\n", - entry->name, oid_to_hex(&entry->entry.oid)); - break; - default: - test_msg("BUG: invalid return value (%d) from key_val_contains()", - ret); - break; - } - } else { - count++; - } - } - check_int(count, ==, ARRAY_SIZE(key_val)); - check_int(hashmap_get_size(&map->map), ==, ARRAY_SIZE(key_val)); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST(setup(t_replace), "replace works"); - TEST(setup(t_get), "get works"); - TEST(setup(t_remove), "remove works"); - TEST(setup(t_iterate), "iterate works"); - return test_done(); -} diff --git a/t/unit-tests/t-oidtree.c b/t/unit-tests/t-oidtree.c deleted file mode 100644 index a38754b066..0000000000 --- a/t/unit-tests/t-oidtree.c +++ /dev/null @@ -1,122 +0,0 @@ -#include "test-lib.h" -#include "lib-oid.h" -#include "oidtree.h" -#include "hash.h" -#include "hex.h" -#include "strvec.h" - -#define FILL_TREE(tree, ...) \ - do { \ - const char *hexes[] = { __VA_ARGS__ }; \ - if (fill_tree_loc(tree, hexes, ARRAY_SIZE(hexes))) \ - return; \ - } while (0) - -static int fill_tree_loc(struct oidtree *ot, const char *hexes[], size_t n) -{ - for (size_t i = 0; i < n; i++) { - struct object_id oid; - if (!check_int(get_oid_arbitrary_hex(hexes[i], &oid), ==, 0)) - return -1; - oidtree_insert(ot, &oid); - } - return 0; -} - -static void check_contains(struct oidtree *ot, const char *hex, int expected) -{ - struct object_id oid; - - if (!check_int(get_oid_arbitrary_hex(hex, &oid), ==, 0)) - return; - if (!check_int(oidtree_contains(ot, &oid), ==, expected)) - test_msg("oid: %s", oid_to_hex(&oid)); -} - -struct expected_hex_iter { - size_t i; - struct strvec expected_hexes; - const char *query; -}; - -static enum cb_next check_each_cb(const struct object_id *oid, void *data) -{ - struct expected_hex_iter *hex_iter = data; - struct object_id expected; - - if (!check_int(hex_iter->i, <, hex_iter->expected_hexes.nr)) { - test_msg("error: extraneous callback for query: ('%s'), object_id: ('%s')", - hex_iter->query, oid_to_hex(oid)); - return CB_BREAK; - } - - if (!check_int(get_oid_arbitrary_hex(hex_iter->expected_hexes.v[hex_iter->i], - &expected), ==, 0)) - ; /* the data is bogus and cannot be used */ - else if (!check(oideq(oid, &expected))) - test_msg("expected: %s\n got: %s\n query: %s", - oid_to_hex(&expected), oid_to_hex(oid), hex_iter->query); - - hex_iter->i += 1; - return CB_CONTINUE; -} - -LAST_ARG_MUST_BE_NULL -static void check_each(struct oidtree *ot, const char *query, ...) -{ - struct object_id oid; - struct expected_hex_iter hex_iter = { .expected_hexes = STRVEC_INIT, - .query = query }; - const char *arg; - va_list hex_args; - - va_start(hex_args, query); - while ((arg = va_arg(hex_args, const char *))) - strvec_push(&hex_iter.expected_hexes, arg); - va_end(hex_args); - - if (!check_int(get_oid_arbitrary_hex(query, &oid), ==, 0)) - return; - oidtree_each(ot, &oid, strlen(query), check_each_cb, &hex_iter); - - if (!check_int(hex_iter.i, ==, hex_iter.expected_hexes.nr)) - test_msg("error: could not find some 'object_id's for query ('%s')", query); - strvec_clear(&hex_iter.expected_hexes); -} - -static void setup(void (*f)(struct oidtree *ot)) -{ - struct oidtree ot; - - oidtree_init(&ot); - f(&ot); - oidtree_clear(&ot); -} - -static void t_contains(struct oidtree *ot) -{ - FILL_TREE(ot, "444", "1", "2", "3", "4", "5", "a", "b", "c", "d", "e"); - check_contains(ot, "44", 0); - check_contains(ot, "441", 0); - check_contains(ot, "440", 0); - check_contains(ot, "444", 1); - check_contains(ot, "4440", 1); - check_contains(ot, "4444", 0); -} - -static void t_each(struct oidtree *ot) -{ - FILL_TREE(ot, "f", "9", "8", "123", "321", "320", "a", "b", "c", "d", "e"); - check_each(ot, "12300", "123", NULL); - check_each(ot, "3211", NULL); /* should not reach callback */ - check_each(ot, "3210", "321", NULL); - check_each(ot, "32100", "321", NULL); - check_each(ot, "32", "320", "321", NULL); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST(setup(t_contains), "oidtree insert and contains works"); - TEST(setup(t_each), "oidtree each works"); - return test_done(); -} diff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c deleted file mode 100644 index a053635000..0000000000 --- a/t/unit-tests/t-prio-queue.c +++ /dev/null @@ -1,91 +0,0 @@ -#include "test-lib.h" -#include "prio-queue.h" - -static int intcmp(const void *va, const void *vb, void *data UNUSED) -{ - const int *a = va, *b = vb; - return *a - *b; -} - - -#define MISSING -1 -#define DUMP -2 -#define STACK -3 -#define GET -4 -#define REVERSE -5 - -static int show(int *v) -{ - return v ? *v : MISSING; -} - -static void test_prio_queue(int *input, size_t input_size, - int *result, size_t result_size) -{ - struct prio_queue pq = { intcmp }; - int j = 0; - - for (size_t i = 0; i < input_size; i++) { - void *peek, *get; - switch(input[i]) { - case GET: - peek = prio_queue_peek(&pq); - get = prio_queue_get(&pq); - if (!check(peek == get)) - return; - if (!check_uint(j, <, result_size)) - break; - if (!check_int(result[j], ==, show(get))) - test_msg(" j: %d", j); - j++; - break; - case DUMP: - while ((peek = prio_queue_peek(&pq))) { - get = prio_queue_get(&pq); - if (!check(peek == get)) - return; - if (!check_uint(j, <, result_size)) - break; - if (!check_int(result[j], ==, show(get))) - test_msg(" j: %d", j); - j++; - } - break; - case STACK: - pq.compare = NULL; - break; - case REVERSE: - prio_queue_reverse(&pq); - break; - default: - prio_queue_put(&pq, &input[i]); - break; - } - } - check_uint(j, ==, result_size); - clear_prio_queue(&pq); -} - -#define TEST_INPUT(input, result) \ - test_prio_queue(input, ARRAY_SIZE(input), result, ARRAY_SIZE(result)) - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST(TEST_INPUT(((int []){ 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP }), - ((int []){ 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10 })), - "prio-queue works for basic input"); - TEST(TEST_INPUT(((int []){ 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP }), - ((int []){ 2, 3, 4, 1, 5, 6 })), - "prio-queue works for mixed put & get commands"); - TEST(TEST_INPUT(((int []){ 1, 2, GET, GET, GET, 1, 2, GET, GET, GET }), - ((int []){ 1, 2, MISSING, 1, 2, MISSING })), - "prio-queue works when queue is empty"); - TEST(TEST_INPUT(((int []){ STACK, 8, 1, 5, 4, 6, 2, 3, DUMP }), - ((int []){ 3, 2, 6, 4, 5, 1, 8 })), - "prio-queue works when used as a LIFO stack"); - TEST(TEST_INPUT(((int []){ STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP }), - ((int []){ 1, 2, 3, 4, 5, 6 })), - "prio-queue works when LIFO stack is reversed"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c index 1d640b280f..9ba7eb05ad 100644 --- a/t/unit-tests/t-reftable-basics.c +++ b/t/unit-tests/t-reftable-basics.c @@ -120,7 +120,7 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED) for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { check(!reftable_buf_addstr(&a, cases[i].a)); check(!reftable_buf_addstr(&b, cases[i].b)); - check_int(common_prefix_size(&a, &b), ==, cases[i].want); + check_uint(common_prefix_size(&a, &b), ==, cases[i].want); reftable_buf_reset(&a); reftable_buf_reset(&b); } diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c index 6b75a419b9..c9626831da 100644 --- a/t/unit-tests/t-reftable-readwrite.c +++ b/t/unit-tests/t-reftable-readwrite.c @@ -108,8 +108,8 @@ static void t_log_buffer_size(void) hash, to ensure that the compressed part is larger than the original. */ for (i = 0; i < REFTABLE_HASH_SIZE_SHA1; i++) { - log.value.update.old_hash[i] = (uint8_t)(git_rand() % 256); - log.value.update.new_hash[i] = (uint8_t)(git_rand() % 256); + log.value.update.old_hash[i] = (uint8_t)(git_rand(0) % 256); + log.value.update.new_hash[i] = (uint8_t)(git_rand(0) % 256); } reftable_writer_set_limits(w, update_index, update_index); err = reftable_writer_add_log(w, &log); @@ -325,7 +325,7 @@ static void t_log_zlib_corruption(void) }; for (i = 0; i < sizeof(message) - 1; i++) - message[i] = (uint8_t)(git_rand() % 64 + ' '); + message[i] = (uint8_t)(git_rand(0) % 64 + ' '); reftable_writer_set_limits(w, 1, 1); @@ -643,7 +643,7 @@ static void t_write_empty_table(void) check_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR); reftable_writer_free(w); - check_int(buf.len, ==, header_size(1) + footer_size(1)); + check_uint(buf.len, ==, header_size(1) + footer_size(1)); block_source_from_buf(&source, &buf); diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c index 42bc64cec8..d49d2a2729 100644 --- a/t/unit-tests/t-reftable-record.c +++ b/t/unit-tests/t-reftable-record.c @@ -58,9 +58,25 @@ static void t_varint_roundtrip(void) } } +static void t_varint_overflow(void) +{ + unsigned char buf[] = { + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, + }; + struct string_view view = { + .buf = buf, + .len = sizeof(buf), + }; + uint64_t value; + int err = get_var_int(&value, &view); + check_int(err, ==, -1); +} + static void set_hash(uint8_t *h, int j) { - for (int i = 0; i < hash_size(REFTABLE_HASH_SHA1); i++) + for (size_t i = 0; i < hash_size(REFTABLE_HASH_SHA1); i++) h[i] = (j >> i) & 0xff; } @@ -544,6 +560,7 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED) TEST(t_reftable_log_record_roundtrip(), "record operations work on log record"); TEST(t_reftable_ref_record_roundtrip(), "record operations work on ref record"); TEST(t_varint_roundtrip(), "put_var_int and get_var_int work"); + TEST(t_varint_overflow(), "get_var_int notices an integer overflow"); TEST(t_key_roundtrip(), "reftable_encode_key and reftable_decode_key work"); TEST(t_reftable_obj_record_roundtrip(), "record operations work on obj record"); TEST(t_reftable_index_record_roundtrip(), "record operations work on index record"); diff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c index aeec195b2b..c3f0059c34 100644 --- a/t/unit-tests/t-reftable-stack.c +++ b/t/unit-tests/t-reftable-stack.c @@ -103,7 +103,8 @@ static void t_read_file(void) static int write_test_ref(struct reftable_writer *wr, void *arg) { struct reftable_ref_record *ref = arg; - reftable_writer_set_limits(wr, ref->update_index, ref->update_index); + check(!reftable_writer_set_limits(wr, ref->update_index, + ref->update_index)); return reftable_writer_add_ref(wr, ref); } @@ -143,7 +144,8 @@ static int write_test_log(struct reftable_writer *wr, void *arg) { struct write_log_arg *wla = arg; - reftable_writer_set_limits(wr, wla->update_index, wla->update_index); + check(!reftable_writer_set_limits(wr, wla->update_index, + wla->update_index)); return reftable_writer_add_log(wr, wla->log); } @@ -961,7 +963,7 @@ static void t_reflog_expire(void) static int write_nothing(struct reftable_writer *wr, void *arg UNUSED) { - reftable_writer_set_limits(wr, 1, 1); + check(!reftable_writer_set_limits(wr, 1, 1)); return 0; } @@ -1369,11 +1371,57 @@ static void t_reftable_stack_reload_with_missing_table(void) clear_dir(dir); } +static int write_limits_after_ref(struct reftable_writer *wr, void *arg) +{ + struct reftable_ref_record *ref = arg; + check(!reftable_writer_set_limits(wr, ref->update_index, ref->update_index)); + check(!reftable_writer_add_ref(wr, ref)); + return reftable_writer_set_limits(wr, ref->update_index, ref->update_index); +} + +static void t_reftable_invalid_limit_updates(void) +{ + struct reftable_ref_record ref = { + .refname = (char *) "HEAD", + .update_index = 1, + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *) "master", + }; + struct reftable_write_options opts = { + .default_permissions = 0660, + }; + struct reftable_addition *add = NULL; + char *dir = get_tmp_dir(__LINE__); + struct reftable_stack *st = NULL; + int err; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + reftable_addition_destroy(add); + + err = reftable_stack_new_addition(&add, st, 0); + check(!err); + + /* + * write_limits_after_ref also updates the update indexes after adding + * the record. This should cause an err to be returned, since the limits + * must be set at the start. + */ + err = reftable_addition_add(add, write_limits_after_ref, &ref); + check_int(err, ==, REFTABLE_API_ERROR); + + reftable_addition_destroy(add); + reftable_stack_destroy(st); + clear_dir(dir); +} + int cmd_main(int argc UNUSED, const char *argv[] UNUSED) { TEST(t_empty_add(), "empty addition to stack"); TEST(t_read_file(), "read_lines works"); TEST(t_reflog_expire(), "expire reflog entries"); + TEST(t_reftable_invalid_limit_updates(), "prevent limit updates after adding records"); TEST(t_reftable_stack_add(), "add multiple refs and logs to stack"); TEST(t_reftable_stack_add_one(), "add a single ref record to stack"); TEST(t_reftable_stack_add_performs_auto_compaction(), "addition to stack triggers auto-compaction"); diff --git a/t/unit-tests/t-strbuf.c b/t/unit-tests/t-strbuf.c deleted file mode 100644 index 3f4044d697..0000000000 --- a/t/unit-tests/t-strbuf.c +++ /dev/null @@ -1,122 +0,0 @@ -#include "test-lib.h" -#include "strbuf.h" - -/* wrapper that supplies tests with an empty, initialized strbuf */ -static void setup(void (*f)(struct strbuf*, const void*), - const void *data) -{ - struct strbuf buf = STRBUF_INIT; - - f(&buf, data); - strbuf_release(&buf); - check_uint(buf.len, ==, 0); - check_uint(buf.alloc, ==, 0); -} - -/* wrapper that supplies tests with a populated, initialized strbuf */ -static void setup_populated(void (*f)(struct strbuf*, const void*), - const char *init_str, const void *data) -{ - struct strbuf buf = STRBUF_INIT; - - strbuf_addstr(&buf, init_str); - check_uint(buf.len, ==, strlen(init_str)); - f(&buf, data); - strbuf_release(&buf); - check_uint(buf.len, ==, 0); - check_uint(buf.alloc, ==, 0); -} - -static int assert_sane_strbuf(struct strbuf *buf) -{ - /* Initialized strbufs should always have a non-NULL buffer */ - if (!check(!!buf->buf)) - return 0; - /* Buffers should always be NUL-terminated */ - if (!check_char(buf->buf[buf->len], ==, '\0')) - return 0; - /* - * Freshly-initialized strbufs may not have a dynamically allocated - * buffer - */ - if (buf->len == 0 && buf->alloc == 0) - return 1; - /* alloc must be at least one byte larger than len */ - return check_uint(buf->len, <, buf->alloc); -} - -static void t_static_init(void) -{ - struct strbuf buf = STRBUF_INIT; - - check_uint(buf.len, ==, 0); - check_uint(buf.alloc, ==, 0); - check_char(buf.buf[0], ==, '\0'); -} - -static void t_dynamic_init(void) -{ - struct strbuf buf; - - strbuf_init(&buf, 1024); - check(assert_sane_strbuf(&buf)); - check_uint(buf.len, ==, 0); - check_uint(buf.alloc, >=, 1024); - check_char(buf.buf[0], ==, '\0'); - strbuf_release(&buf); -} - -static void t_addch(struct strbuf *buf, const void *data) -{ - const char *p_ch = data; - const char ch = *p_ch; - size_t orig_alloc = buf->alloc; - size_t orig_len = buf->len; - - if (!check(assert_sane_strbuf(buf))) - return; - strbuf_addch(buf, ch); - if (!check(assert_sane_strbuf(buf))) - return; - if (!(check_uint(buf->len, ==, orig_len + 1) && - check_uint(buf->alloc, >=, orig_alloc))) - return; /* avoid de-referencing buf->buf */ - check_char(buf->buf[buf->len - 1], ==, ch); - check_char(buf->buf[buf->len], ==, '\0'); -} - -static void t_addstr(struct strbuf *buf, const void *data) -{ - const char *text = data; - size_t len = strlen(text); - size_t orig_alloc = buf->alloc; - size_t orig_len = buf->len; - - if (!check(assert_sane_strbuf(buf))) - return; - strbuf_addstr(buf, text); - if (!check(assert_sane_strbuf(buf))) - return; - if (!(check_uint(buf->len, ==, orig_len + len) && - check_uint(buf->alloc, >=, orig_alloc) && - check_uint(buf->alloc, >, orig_len + len) && - check_char(buf->buf[orig_len + len], ==, '\0'))) - return; - check_str(buf->buf + orig_len, text); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - if (!TEST(t_static_init(), "static initialization works")) - test_skip_all("STRBUF_INIT is broken"); - TEST(t_dynamic_init(), "dynamic initialization works"); - TEST(setup(t_addch, "a"), "strbuf_addch adds char"); - TEST(setup(t_addch, ""), "strbuf_addch adds NUL char"); - TEST(setup_populated(t_addch, "initial value", "a"), - "strbuf_addch appends to initial value"); - TEST(setup(t_addstr, "hello there"), "strbuf_addstr adds string"); - TEST(setup_populated(t_addstr, "initial value", "hello there"), - "strbuf_addstr appends string to initial value"); - - return test_done(); -} diff --git a/t/unit-tests/t-strcmp-offset.c b/t/unit-tests/t-strcmp-offset.c deleted file mode 100644 index 6880f21161..0000000000 --- a/t/unit-tests/t-strcmp-offset.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "test-lib.h" -#include "read-cache-ll.h" - -static void check_strcmp_offset(const char *string1, const char *string2, - int expect_result, uintmax_t expect_offset) -{ - size_t offset; - int result = strcmp_offset(string1, string2, &offset); - - /* - * Because different CRTs behave differently, only rely on signs of the - * result values. - */ - result = (result < 0 ? -1 : - result > 0 ? 1 : - 0); - - check_int(result, ==, expect_result); - check_uint((uintmax_t)offset, ==, expect_offset); -} - -#define TEST_STRCMP_OFFSET(string1, string2, expect_result, expect_offset) \ - TEST(check_strcmp_offset(string1, string2, expect_result, \ - expect_offset), \ - "strcmp_offset(%s, %s) works", #string1, #string2) - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST_STRCMP_OFFSET("abc", "abc", 0, 3); - TEST_STRCMP_OFFSET("abc", "def", -1, 0); - TEST_STRCMP_OFFSET("abc", "abz", -1, 2); - TEST_STRCMP_OFFSET("abc", "abcdef", -1, 3); - - return test_done(); -} diff --git a/t/unit-tests/u-example-decorate.c b/t/unit-tests/u-example-decorate.c new file mode 100644 index 0000000000..9b1d1ce753 --- /dev/null +++ b/t/unit-tests/u-example-decorate.c @@ -0,0 +1,64 @@ +#define USE_THE_REPOSITORY_VARIABLE + +#include "unit-test.h" +#include "object.h" +#include "decorate.h" +#include "repository.h" + +struct test_vars { + struct object *one, *two, *three; + struct decoration n; + int decoration_a, decoration_b; +}; + +static struct test_vars vars; + +void test_example_decorate__initialize(void) +{ + struct object_id one_oid = { { 1 } }, two_oid = { { 2 } }, three_oid = { { 3 } }; + + vars.one = lookup_unknown_object(the_repository, &one_oid); + vars.two = lookup_unknown_object(the_repository, &two_oid); + vars.three = lookup_unknown_object(the_repository, &three_oid); +} + +void test_example_decorate__cleanup(void) +{ + clear_decoration(&vars.n, NULL); +} + +void test_example_decorate__add(void) +{ + cl_assert_equal_p(add_decoration(&vars.n, vars.one, &vars.decoration_a), NULL); + cl_assert_equal_p(add_decoration(&vars.n, vars.two, NULL), NULL); +} + +void test_example_decorate__readd(void) +{ + cl_assert_equal_p(add_decoration(&vars.n, vars.one, &vars.decoration_a), NULL); + cl_assert_equal_p(add_decoration(&vars.n, vars.two, NULL), NULL); + cl_assert_equal_p(add_decoration(&vars.n, vars.one, NULL), &vars.decoration_a); + cl_assert_equal_p(add_decoration(&vars.n, vars.two, &vars.decoration_b), NULL); +} + +void test_example_decorate__lookup(void) +{ + cl_assert_equal_p(add_decoration(&vars.n, vars.two, &vars.decoration_b), NULL); + cl_assert_equal_p(add_decoration(&vars.n, vars.one, NULL), NULL); + cl_assert_equal_p(lookup_decoration(&vars.n, vars.two), &vars.decoration_b); + cl_assert_equal_p(lookup_decoration(&vars.n, vars.one), NULL); +} + +void test_example_decorate__loop(void) +{ + int objects_noticed = 0; + + cl_assert_equal_p(add_decoration(&vars.n, vars.one, &vars.decoration_a), NULL); + cl_assert_equal_p(add_decoration(&vars.n, vars.two, &vars.decoration_b), NULL); + + for (size_t i = 0; i < vars.n.size; i++) + if (vars.n.entries[i].base) + objects_noticed++; + + cl_assert_equal_i(objects_noticed, 2); +} diff --git a/t/unit-tests/t-hash.c b/t/unit-tests/u-hash.c index e62647019b..bd4ac6a6e1 100644 --- a/t/unit-tests/t-hash.c +++ b/t/unit-tests/u-hash.c @@ -1,84 +1,109 @@ -#include "test-lib.h" +#include "unit-test.h" #include "hex.h" #include "strbuf.h" static void check_hash_data(const void *data, size_t data_length, const char *expected_hashes[]) { - if (!check(data != NULL)) { - test_msg("BUG: NULL data pointer provided"); - return; - } + cl_assert(data != NULL); for (size_t i = 1; i < ARRAY_SIZE(hash_algos); i++) { - git_hash_ctx ctx; + struct git_hash_ctx ctx; unsigned char hash[GIT_MAX_HEXSZ]; const struct git_hash_algo *algop = &hash_algos[i]; algop->init_fn(&ctx); - algop->update_fn(&ctx, data, data_length); - algop->final_fn(hash, &ctx); + git_hash_update(&ctx, data, data_length); + git_hash_final(hash, &ctx); - if (!check_str(hash_to_hex_algop(hash, algop), expected_hashes[i - 1])) - test_msg("result does not match with the expected for %s\n", hash_algos[i].name); + cl_assert_equal_s(hash_to_hex_algop(hash,algop), expected_hashes[i - 1]); } } /* Works with a NUL terminated string. Doesn't work if it should contain a NUL character. */ #define TEST_HASH_STR(data, expected_sha1, expected_sha256) do { \ const char *expected_hashes[] = { expected_sha1, expected_sha256 }; \ - TEST(check_hash_data(data, strlen(data), expected_hashes), \ - "SHA1 and SHA256 (%s) works", #data); \ + check_hash_data(data, strlen(data), expected_hashes); \ } while (0) /* Only works with a literal string, useful when it contains a NUL character. */ #define TEST_HASH_LITERAL(literal, expected_sha1, expected_sha256) do { \ const char *expected_hashes[] = { expected_sha1, expected_sha256 }; \ - TEST(check_hash_data(literal, (sizeof(literal) - 1), expected_hashes), \ - "SHA1 and SHA256 (%s) works", #literal); \ + check_hash_data(literal, (sizeof(literal) - 1), expected_hashes); \ } while (0) -int cmd_main(int argc UNUSED, const char **argv UNUSED) +void test_hash__empty_string(void) { - struct strbuf aaaaaaaaaa_100000 = STRBUF_INIT; - struct strbuf alphabet_100000 = STRBUF_INIT; - - strbuf_addstrings(&aaaaaaaaaa_100000, "aaaaaaaaaa", 100000); - strbuf_addstrings(&alphabet_100000, "abcdefghijklmnopqrstuvwxyz", 100000); - TEST_HASH_STR("", "da39a3ee5e6b4b0d3255bfef95601890afd80709", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); +} + +void test_hash__single_character(void) +{ TEST_HASH_STR("a", "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8", "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"); +} + +void test_hash__multi_character(void) +{ TEST_HASH_STR("abc", "a9993e364706816aba3e25717850c26c9cd0d89d", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); +} + +void test_hash__message_digest(void) +{ TEST_HASH_STR("message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3", "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650"); +} + +void test_hash__alphabet(void) +{ TEST_HASH_STR("abcdefghijklmnopqrstuvwxyz", "32d10c7b8cf96570ca04ce37f2a19d84240d3a89", "71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73"); +} + +void test_hash__aaaaaaaaaa_100000(void) +{ + struct strbuf aaaaaaaaaa_100000 = STRBUF_INIT; + strbuf_addstrings(&aaaaaaaaaa_100000, "aaaaaaaaaa", 100000); TEST_HASH_STR(aaaaaaaaaa_100000.buf, "34aa973cd4c4daa4f61eeb2bdbad27316534016f", "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"); + strbuf_release(&aaaaaaaaaa_100000); +} + +void test_hash__alphabet_100000(void) +{ + struct strbuf alphabet_100000 = STRBUF_INIT; + strbuf_addstrings(&alphabet_100000, "abcdefghijklmnopqrstuvwxyz", 100000); TEST_HASH_STR(alphabet_100000.buf, "e7da7c55b3484fdf52aebec9cbe7b85a98f02fd4", "e406ba321ca712ad35a698bf0af8d61fc4dc40eca6bdcea4697962724ccbde35"); + strbuf_release(&alphabet_100000); +} + +void test_hash__zero_blob_literal(void) +{ TEST_HASH_LITERAL("blob 0\0", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"); +} + +void test_hash__three_blob_literal(void) +{ TEST_HASH_LITERAL("blob 3\0abc", "f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f", "c1cf6e465077930e88dc5136641d402f72a229ddd996f627d60e9639eaba35a6"); +} + +void test_hash__zero_tree_literal(void) +{ TEST_HASH_LITERAL("tree 0\0", "4b825dc642cb6eb9a060e54bf8d69288fbee4904", "6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321"); - - strbuf_release(&aaaaaaaaaa_100000); - strbuf_release(&alphabet_100000); - - return test_done(); } diff --git a/t/unit-tests/t-hashmap.c b/t/unit-tests/u-hashmap.c index 83b79dff39..eb80aa1348 100644 --- a/t/unit-tests/t-hashmap.c +++ b/t/unit-tests/u-hashmap.c @@ -1,4 +1,4 @@ -#include "test-lib.h" +#include "unit-test.h" #include "hashmap.h" #include "strbuf.h" @@ -83,23 +83,23 @@ static void t_replace(struct hashmap *map, unsigned int ignore_case) struct test_entry *entry; entry = alloc_test_entry("key1", "value1", ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); entry = alloc_test_entry(ignore_case ? "Key1" : "key1", "value2", ignore_case); entry = hashmap_put_entry(map, entry, ent); - if (check(entry != NULL)) - check_str(get_value(entry), "value1"); + cl_assert(entry != NULL); + cl_assert_equal_s(get_value(entry), "value1"); free(entry); entry = alloc_test_entry("fooBarFrotz", "value3", ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); entry = alloc_test_entry(ignore_case ? "FOObarFrotz" : "fooBarFrotz", "value4", ignore_case); entry = hashmap_put_entry(map, entry, ent); - if (check(entry != NULL)) - check_str(get_value(entry), "value3"); + cl_assert(entry != NULL); + cl_assert_equal_s(get_value(entry), "value3"); free(entry); } @@ -122,20 +122,18 @@ static void t_get(struct hashmap *map, unsigned int ignore_case) for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { entry = alloc_test_entry(key_val[i][0], key_val[i][1], ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); } for (size_t i = 0; i < ARRAY_SIZE(query); i++) { entry = get_test_entry(map, query[i][0], ignore_case); - if (check(entry != NULL)) - check_str(get_value(entry), query[i][1]); - else - test_msg("query key: %s", query[i][0]); + cl_assert(entry != NULL); + cl_assert_equal_s(get_value(entry), query[i][1]); } - check_pointer_eq(get_test_entry(map, "notInMap", ignore_case), NULL); - check_int(map->tablesize, ==, 64); - check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val)); + cl_assert_equal_p(get_test_entry(map, "notInMap", ignore_case), NULL); + cl_assert_equal_i(map->tablesize, 64); + cl_assert_equal_i(hashmap_get_size(map), ARRAY_SIZE(key_val)); } static void t_add(struct hashmap *map, unsigned int ignore_case) @@ -165,39 +163,19 @@ static void t_add(struct hashmap *map, unsigned int ignore_case) hashmap_for_each_entry_from(map, entry, ent) { - int ret; - if (!check_int((ret = key_val_contains( - key_val, seen, - ARRAY_SIZE(key_val), entry)), - ==, 0)) { - switch (ret) { - case 1: - test_msg("found entry was not given in the input\n" - " key: %s\n value: %s", - entry->key, get_value(entry)); - break; - case 2: - test_msg("duplicate entry detected\n" - " key: %s\n value: %s", - entry->key, get_value(entry)); - break; - } - } else { - count++; - } + int ret = key_val_contains(key_val, seen, + ARRAY_SIZE(key_val), entry); + cl_assert_equal_i(ret, 0); + count++; } - check_int(count, ==, 2); + cl_assert_equal_i(count, 2); } - for (size_t i = 0; i < ARRAY_SIZE(seen); i++) { - if (!check_int(seen[i], ==, 1)) - test_msg("following key-val pair was not iterated over:\n" - " key: %s\n value: %s", - key_val[i][0], key_val[i][1]); - } + for (size_t i = 0; i < ARRAY_SIZE(seen); i++) + cl_assert_equal_i(seen[i], 1); - check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val)); - check_pointer_eq(get_test_entry(map, "notInMap", ignore_case), NULL); + cl_assert_equal_i(hashmap_get_size(map), ARRAY_SIZE(key_val)); + cl_assert_equal_p(get_test_entry(map, "notInMap", ignore_case), NULL); } static void t_remove(struct hashmap *map, unsigned int ignore_case) @@ -211,24 +189,25 @@ static void t_remove(struct hashmap *map, unsigned int ignore_case) for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { entry = alloc_test_entry(key_val[i][0], key_val[i][1], ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); } for (size_t i = 0; i < ARRAY_SIZE(remove); i++) { entry = alloc_test_entry(remove[i][0], "", ignore_case); removed = hashmap_remove_entry(map, entry, ent, remove[i][0]); - if (check(removed != NULL)) - check_str(get_value(removed), remove[i][1]); + cl_assert(removed != NULL); + cl_assert_equal_s(get_value(removed), remove[i][1]); free(entry); free(removed); } entry = alloc_test_entry("notInMap", "", ignore_case); - check_pointer_eq(hashmap_remove_entry(map, entry, ent, "notInMap"), NULL); + cl_assert_equal_p(hashmap_remove_entry(map, entry, ent, "notInMap"), NULL); free(entry); - check_int(map->tablesize, ==, 64); - check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val) - ARRAY_SIZE(remove)); + cl_assert_equal_i(map->tablesize, 64); + cl_assert_equal_i(hashmap_get_size(map), + ARRAY_SIZE(key_val) - ARRAY_SIZE(remove)); } static void t_iterate(struct hashmap *map, unsigned int ignore_case) @@ -242,38 +221,21 @@ static void t_iterate(struct hashmap *map, unsigned int ignore_case) for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { entry = alloc_test_entry(key_val[i][0], key_val[i][1], ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); } hashmap_for_each_entry(map, &iter, entry, ent /* member name */) { - int ret; - if (!check_int((ret = key_val_contains(key_val, seen, - ARRAY_SIZE(key_val), - entry)), ==, 0)) { - switch (ret) { - case 1: - test_msg("found entry was not given in the input\n" - " key: %s\n value: %s", - entry->key, get_value(entry)); - break; - case 2: - test_msg("duplicate entry detected\n" - " key: %s\n value: %s", - entry->key, get_value(entry)); - break; - } - } + int ret = key_val_contains(key_val, seen, + ARRAY_SIZE(key_val), + entry); + cl_assert(ret == 0); } - for (size_t i = 0; i < ARRAY_SIZE(seen); i++) { - if (!check_int(seen[i], ==, 1)) - test_msg("following key-val pair was not iterated over:\n" - " key: %s\n value: %s", - key_val[i][0], key_val[i][1]); - } + for (size_t i = 0; i < ARRAY_SIZE(seen); i++) + cl_assert_equal_i(seen[i], 1); - check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val)); + cl_assert_equal_i(hashmap_get_size(map), ARRAY_SIZE(key_val)); } static void t_alloc(struct hashmap *map, unsigned int ignore_case) @@ -284,17 +246,17 @@ static void t_alloc(struct hashmap *map, unsigned int ignore_case) char *key = xstrfmt("key%d", i); char *value = xstrfmt("value%d", i); entry = alloc_test_entry(key, value, ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); free(key); free(value); } - check_int(map->tablesize, ==, 64); - check_int(hashmap_get_size(map), ==, 51); + cl_assert_equal_i(map->tablesize, 64); + cl_assert_equal_i(hashmap_get_size(map), 51); entry = alloc_test_entry("key52", "value52", ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); - check_int(map->tablesize, ==, 256); - check_int(hashmap_get_size(map), ==, 52); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_i(map->tablesize, 256); + cl_assert_equal_i(hashmap_get_size(map), 52); for (int i = 1; i <= 12; i++) { char *key = xstrfmt("key%d", i); @@ -302,27 +264,27 @@ static void t_alloc(struct hashmap *map, unsigned int ignore_case) entry = alloc_test_entry(key, "", ignore_case); removed = hashmap_remove_entry(map, entry, ent, key); - if (check(removed != NULL)) - check_str(value, get_value(removed)); + cl_assert(removed != NULL); + cl_assert_equal_s(value, get_value(removed)); free(key); free(value); free(entry); free(removed); } - check_int(map->tablesize, ==, 256); - check_int(hashmap_get_size(map), ==, 40); + cl_assert_equal_i(map->tablesize, 256); + cl_assert_equal_i(hashmap_get_size(map), 40); entry = alloc_test_entry("key40", "", ignore_case); removed = hashmap_remove_entry(map, entry, ent, "key40"); - if (check(removed != NULL)) - check_str("value40", get_value(removed)); - check_int(map->tablesize, ==, 64); - check_int(hashmap_get_size(map), ==, 39); + cl_assert(removed != NULL); + cl_assert_equal_s("value40", get_value(removed)); + cl_assert_equal_i(map->tablesize, 64); + cl_assert_equal_i(hashmap_get_size(map), 39); free(entry); free(removed); } -static void t_intern(void) +void test_hashmap__intern(void) { const char *values[] = { "value1", "Value1", "value2", "value2" }; @@ -330,32 +292,68 @@ static void t_intern(void) const char *i1 = strintern(values[i]); const char *i2 = strintern(values[i]); - if (!check(!strcmp(i1, values[i]))) - test_msg("strintern(%s) returns %s\n", values[i], i1); - else if (!check(i1 != values[i])) - test_msg("strintern(%s) returns input pointer\n", - values[i]); - else if (!check_pointer_eq(i1, i2)) - test_msg("address('%s') != address('%s'), so strintern('%s') != strintern('%s')", - i1, i2, values[i], values[i]); - else - check_str(i1, values[i]); + cl_assert_equal_s(i1, values[i]); + cl_assert(i1 != values[i]); + cl_assert_equal_p(i1, i2); } } -int cmd_main(int argc UNUSED, const char **argv UNUSED) +void test_hashmap__replace_case_sensitive(void) +{ + setup(t_replace, 0); +} + +void test_hashmap__replace_case_insensitive(void) +{ + setup(t_replace, 1); +} + +void test_hashmap__get_case_sensitive(void) +{ + setup(t_get, 0); +} + +void test_hashmap__get_case_insensitive(void) +{ + setup(t_get, 1); +} + +void test_hashmap__add_case_sensitive(void) +{ + setup(t_add, 0); +} + +void test_hashmap__add_case_insensitive(void) +{ + setup(t_add, 1); +} + +void test_hashmap__remove_case_sensitive(void) +{ + setup(t_remove, 0); +} + +void test_hashmap__remove_case_insensitive(void) +{ + setup(t_remove, 1); +} + +void test_hashmap__iterate_case_sensitive(void) +{ + setup(t_iterate, 0); +} + +void test_hashmap__iterate_case_insensitive(void) +{ + setup(t_iterate, 1); +} + +void test_hashmap__alloc_case_sensitive(void) +{ + setup(t_alloc, 0); +} + +void test_hashmap__alloc_case_insensitive(void) { - TEST(setup(t_replace, 0), "replace works"); - TEST(setup(t_replace, 1), "replace (case insensitive) works"); - TEST(setup(t_get, 0), "get works"); - TEST(setup(t_get, 1), "get (case insensitive) works"); - TEST(setup(t_add, 0), "add works"); - TEST(setup(t_add, 1), "add (case insensitive) works"); - TEST(setup(t_remove, 0), "remove works"); - TEST(setup(t_remove, 1), "remove (case insensitive) works"); - TEST(setup(t_iterate, 0), "iterate works"); - TEST(setup(t_iterate, 1), "iterate (case insensitive) works"); - TEST(setup(t_alloc, 0), "grow / shrink works"); - TEST(t_intern(), "string interning works"); - return test_done(); + setup(t_alloc, 1); } diff --git a/t/unit-tests/u-mem-pool.c b/t/unit-tests/u-mem-pool.c new file mode 100644 index 0000000000..2bc2493b7e --- /dev/null +++ b/t/unit-tests/u-mem-pool.c @@ -0,0 +1,25 @@ +#include "unit-test.h" +#include "mem-pool.h" + +static void test_many_pool_allocations(size_t block_alloc) +{ + struct mem_pool pool = { .block_alloc = block_alloc }; + size_t size = 100; + char *buffer = mem_pool_calloc(&pool, 1, size); + for (size_t i = 0; i < size; i++) + cl_assert_equal_i(0, buffer[i]); + cl_assert(pool.mp_block != NULL); + cl_assert(pool.mp_block->next_free != NULL); + cl_assert(pool.mp_block->end != NULL); + mem_pool_discard(&pool, 0); +} + +void test_mem_pool__big_block(void) +{ + test_many_pool_allocations(1024 * 1024); +} + +void test_mem_pool__tiny_block(void) +{ + test_many_pool_allocations(1); +} diff --git a/t/unit-tests/u-oid-array.c b/t/unit-tests/u-oid-array.c new file mode 100644 index 0000000000..e48a433f21 --- /dev/null +++ b/t/unit-tests/u-oid-array.c @@ -0,0 +1,129 @@ +#define USE_THE_REPOSITORY_VARIABLE + +#include "unit-test.h" +#include "lib-oid.h" +#include "oid-array.h" +#include "hex.h" + +static void fill_array(struct oid_array *array, const char *hexes[], size_t n) +{ + for (size_t i = 0; i < n; i++) { + struct object_id oid; + + cl_parse_any_oid(hexes[i], &oid); + oid_array_append(array, &oid); + } + cl_assert_equal_i(array->nr, n); +} + +static int add_to_oid_array(const struct object_id *oid, void *data) +{ + struct oid_array *array = data; + + oid_array_append(array, oid); + return 0; +} + +static void t_enumeration(const char **input_args, size_t input_sz, + const char **expect_args, size_t expect_sz) +{ + struct oid_array input = OID_ARRAY_INIT, expect = OID_ARRAY_INIT, + actual = OID_ARRAY_INIT; + size_t i; + + fill_array(&input, input_args, input_sz); + fill_array(&expect, expect_args, expect_sz); + + oid_array_for_each_unique(&input, add_to_oid_array, &actual); + cl_assert_equal_i(actual.nr, expect.nr); + + for (i = 0; i < actual.nr; i++) + cl_assert(oideq(&actual.oid[i], &expect.oid[i])); + + oid_array_clear(&actual); + oid_array_clear(&input); + oid_array_clear(&expect); +} + +#define TEST_ENUMERATION(input, expect) \ + t_enumeration(input, ARRAY_SIZE(input), expect, ARRAY_SIZE(expect)); + +static void t_lookup(const char **input_hexes, size_t n, const char *query_hex, + int lower_bound, int upper_bound) +{ + struct oid_array array = OID_ARRAY_INIT; + struct object_id oid_query; + int ret; + + cl_parse_any_oid(query_hex, &oid_query); + fill_array(&array, input_hexes, n); + ret = oid_array_lookup(&array, &oid_query); + + cl_assert(ret <= upper_bound); + cl_assert(ret >= lower_bound); + + oid_array_clear(&array); +} + +#define TEST_LOOKUP(input_hexes, query, lower_bound, upper_bound) \ + t_lookup(input_hexes, ARRAY_SIZE(input_hexes), query, \ + lower_bound, upper_bound); + +void test_oid_array__initialize(void) +{ + /* The hash algo is used by oid_array_lookup() internally */ + int algo = cl_setup_hash_algo(); + repo_set_hash_algo(the_repository, algo); +} + +static const char *arr_input[] = { "88", "44", "aa", "55" }; +static const char *arr_input_dup[] = { "88", "44", "aa", "55", + "88", "44", "aa", "55", + "88", "44", "aa", "55" }; +static const char *res_sorted[] = { "44", "55", "88", "aa" }; + +void test_oid_array__enumerate_unique(void) +{ + TEST_ENUMERATION(arr_input, res_sorted); +} + +void test_oid_array__enumerate_duplicate(void) +{ + TEST_ENUMERATION(arr_input_dup, res_sorted); +} + +void test_oid_array__lookup(void) +{ + TEST_LOOKUP(arr_input, "55", 1, 1); +} + +void test_oid_array__lookup_non_existent(void) +{ + TEST_LOOKUP(arr_input, "33", INT_MIN, -1); +} + +void test_oid_array__lookup_duplicates(void) +{ + TEST_LOOKUP(arr_input_dup, "55", 3, 5); +} + +void test_oid_array__lookup_non_existent_dup(void) +{ + TEST_LOOKUP(arr_input_dup, "66", INT_MIN, -1); +} + +void test_oid_array__lookup_almost_dup(void) +{ + const char *nearly_55; + + nearly_55 = cl_setup_hash_algo() == GIT_HASH_SHA1 ? + "5500000000000000000000000000000000000001" : + "5500000000000000000000000000000000000000000000000000000000000001"; + + TEST_LOOKUP(((const char *[]){ "55", nearly_55 }), "55", 0, 0); +} + +void test_oid_array__lookup_single_dup(void) +{ + TEST_LOOKUP(((const char *[]){ "55", "55" }), "55", 0, 1); +} diff --git a/t/unit-tests/u-oidmap.c b/t/unit-tests/u-oidmap.c new file mode 100644 index 0000000000..dc805b7e3c --- /dev/null +++ b/t/unit-tests/u-oidmap.c @@ -0,0 +1,136 @@ +#include "unit-test.h" +#include "lib-oid.h" +#include "oidmap.h" +#include "hash.h" +#include "hex.h" + +/* + * Elements we will put in oidmap structs are made of a key: the entry.oid + * field, which is of type struct object_id, and a value: the name field (could + * be a refname for example). + */ +struct test_entry { + struct oidmap_entry entry; + char name[FLEX_ARRAY]; +}; + +static const char *const key_val[][2] = { { "11", "one" }, + { "22", "two" }, + { "33", "three" } }; + +static struct oidmap map; + +void test_oidmap__initialize(void) +{ + oidmap_init(&map, 0); + + for (size_t i = 0; i < ARRAY_SIZE(key_val); i++){ + struct test_entry *entry; + + FLEX_ALLOC_STR(entry, name, key_val[i][1]); + cl_parse_any_oid(key_val[i][0], &entry->entry.oid); + cl_assert(oidmap_put(&map, entry) == NULL); + } +} + +void test_oidmap__cleanup(void) +{ + oidmap_free(&map, 1); +} + +void test_oidmap__replace(void) +{ + struct test_entry *entry, *prev; + + FLEX_ALLOC_STR(entry, name, "un"); + cl_parse_any_oid("11", &entry->entry.oid); + prev = oidmap_put(&map, entry); + cl_assert(prev != NULL); + cl_assert_equal_s(prev->name, "one"); + free(prev); + + FLEX_ALLOC_STR(entry, name, "deux"); + cl_parse_any_oid("22", &entry->entry.oid); + prev = oidmap_put(&map, entry); + cl_assert(prev != NULL); + cl_assert_equal_s(prev->name, "two"); + free(prev); +} + +void test_oidmap__get(void) +{ + struct test_entry *entry; + struct object_id oid; + + cl_parse_any_oid("22", &oid); + entry = oidmap_get(&map, &oid); + cl_assert(entry != NULL); + cl_assert_equal_s(entry->name, "two"); + + cl_parse_any_oid("44", &oid); + cl_assert(oidmap_get(&map, &oid) == NULL); + + cl_parse_any_oid("11", &oid); + entry = oidmap_get(&map, &oid); + cl_assert(entry != NULL); + cl_assert_equal_s(entry->name, "one"); +} + +void test_oidmap__remove(void) +{ + struct test_entry *entry; + struct object_id oid; + + cl_parse_any_oid("11", &oid); + entry = oidmap_remove(&map, &oid); + cl_assert(entry != NULL); + cl_assert_equal_s(entry->name, "one"); + cl_assert(oidmap_get(&map, &oid) == NULL); + free(entry); + + cl_parse_any_oid("22", &oid); + entry = oidmap_remove(&map, &oid); + cl_assert(entry != NULL); + cl_assert_equal_s(entry->name, "two"); + cl_assert(oidmap_get(&map, &oid) == NULL); + free(entry); + + cl_parse_any_oid("44", &oid); + cl_assert(oidmap_remove(&map, &oid) == NULL); +} + +static int key_val_contains(struct test_entry *entry, char seen[]) +{ + for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { + struct object_id oid; + + cl_parse_any_oid(key_val[i][0], &oid); + + if (oideq(&entry->entry.oid, &oid)) { + if (seen[i]) + return 2; + seen[i] = 1; + return 0; + } + } + return 1; +} + +void test_oidmap__iterate(void) +{ + struct oidmap_iter iter; + struct test_entry *entry; + char seen[ARRAY_SIZE(key_val)] = { 0 }; + int count = 0; + + oidmap_iter_init(&map, &iter); + while ((entry = oidmap_iter_next(&iter))) { + if (key_val_contains(entry, seen) != 0) { + cl_failf("Unexpected entry: name = %s, oid = %s", + entry->name, oid_to_hex(&entry->entry.oid)); + } + count++; + } + cl_assert_equal_i(count, ARRAY_SIZE(key_val)); + cl_assert_equal_i(hashmap_get_size(&map.map), ARRAY_SIZE(key_val)); +} diff --git a/t/unit-tests/u-oidtree.c b/t/unit-tests/u-oidtree.c new file mode 100644 index 0000000000..e6eede2740 --- /dev/null +++ b/t/unit-tests/u-oidtree.c @@ -0,0 +1,107 @@ +#include "unit-test.h" +#include "lib-oid.h" +#include "oidtree.h" +#include "hash.h" +#include "hex.h" +#include "strvec.h" + +static struct oidtree ot; + +#define FILL_TREE(tree, ...) \ + do { \ + const char *hexes[] = { __VA_ARGS__ }; \ + if (fill_tree_loc(tree, hexes, ARRAY_SIZE(hexes))) \ + return; \ + } while (0) + +static int fill_tree_loc(struct oidtree *ot, const char *hexes[], size_t n) +{ + for (size_t i = 0; i < n; i++) { + struct object_id oid; + cl_parse_any_oid(hexes[i], &oid); + oidtree_insert(ot, &oid); + } + return 0; +} + +static void check_contains(struct oidtree *ot, const char *hex, int expected) +{ + struct object_id oid; + + cl_parse_any_oid(hex, &oid); + cl_assert_equal_i(oidtree_contains(ot, &oid), expected); +} + +struct expected_hex_iter { + size_t i; + struct strvec expected_hexes; + const char *query; +}; + +static enum cb_next check_each_cb(const struct object_id *oid, void *data) +{ + struct expected_hex_iter *hex_iter = data; + struct object_id expected; + + cl_assert(hex_iter->i < hex_iter->expected_hexes.nr); + + cl_parse_any_oid(hex_iter->expected_hexes.v[hex_iter->i], + &expected); + cl_assert_equal_s(oid_to_hex(oid), oid_to_hex(&expected)); + hex_iter->i += 1; + return CB_CONTINUE; +} + +LAST_ARG_MUST_BE_NULL +static void check_each(struct oidtree *ot, const char *query, ...) +{ + struct object_id oid; + struct expected_hex_iter hex_iter = { .expected_hexes = STRVEC_INIT, + .query = query }; + const char *arg; + va_list hex_args; + + va_start(hex_args, query); + while ((arg = va_arg(hex_args, const char *))) + strvec_push(&hex_iter.expected_hexes, arg); + va_end(hex_args); + + cl_parse_any_oid(query, &oid); + oidtree_each(ot, &oid, strlen(query), check_each_cb, &hex_iter); + + if (hex_iter.i != hex_iter.expected_hexes.nr) + cl_failf("error: could not find some 'object_id's for query ('%s')", query); + + strvec_clear(&hex_iter.expected_hexes); +} + +void test_oidtree__initialize(void) +{ + oidtree_init(&ot); +} + +void test_oidtree__cleanup(void) +{ + oidtree_clear(&ot); +} + +void test_oidtree__contains(void) +{ + FILL_TREE(&ot, "444", "1", "2", "3", "4", "5", "a", "b", "c", "d", "e"); + check_contains(&ot, "44", 0); + check_contains(&ot, "441", 0); + check_contains(&ot, "440", 0); + check_contains(&ot, "444", 1); + check_contains(&ot, "4440", 1); + check_contains(&ot, "4444", 0); +} + +void test_oidtree__each(void) +{ + FILL_TREE(&ot, "f", "9", "8", "123", "321", "320", "a", "b", "c", "d", "e"); + check_each(&ot, "12300", "123", NULL); + check_each(&ot, "3211", NULL); /* should not reach callback */ + check_each(&ot, "3210", "321", NULL); + check_each(&ot, "32100", "321", NULL); + check_each(&ot, "32", "320", "321", NULL); +} diff --git a/t/unit-tests/u-prio-queue.c b/t/unit-tests/u-prio-queue.c new file mode 100644 index 0000000000..145e689c9c --- /dev/null +++ b/t/unit-tests/u-prio-queue.c @@ -0,0 +1,94 @@ +#include "unit-test.h" +#include "prio-queue.h" + +static int intcmp(const void *va, const void *vb, void *data UNUSED) +{ + const int *a = va, *b = vb; + return *a - *b; +} + + +#define MISSING -1 +#define DUMP -2 +#define STACK -3 +#define GET -4 +#define REVERSE -5 + +static int show(int *v) +{ + return v ? *v : MISSING; +} + +static void test_prio_queue(int *input, size_t input_size, + int *result, size_t result_size) +{ + struct prio_queue pq = { intcmp }; + size_t j = 0; + + for (size_t i = 0; i < input_size; i++) { + void *peek, *get; + switch(input[i]) { + case GET: + peek = prio_queue_peek(&pq); + get = prio_queue_get(&pq); + cl_assert(peek == get); + cl_assert(j < result_size); + cl_assert_equal_i(result[j], show(get)); + j++; + break; + case DUMP: + while ((peek = prio_queue_peek(&pq))) { + get = prio_queue_get(&pq); + cl_assert(peek == get); + cl_assert(j < result_size); + cl_assert_equal_i(result[j], show(get)); + j++; + } + break; + case STACK: + pq.compare = NULL; + break; + case REVERSE: + prio_queue_reverse(&pq); + break; + default: + prio_queue_put(&pq, &input[i]); + break; + } + } + cl_assert_equal_i(j, result_size); + clear_prio_queue(&pq); +} + +#define TEST_INPUT(input, result) \ + test_prio_queue(input, ARRAY_SIZE(input), result, ARRAY_SIZE(result)) + +void test_prio_queue__basic(void) +{ + TEST_INPUT(((int []){ 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP }), + ((int []){ 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10 })); +} + +void test_prio_queue__mixed(void) +{ + TEST_INPUT(((int []){ 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP }), + ((int []){ 2, 3, 4, 1, 5, 6 })); +} + +void test_prio_queue__empty(void) +{ + TEST_INPUT(((int []){ 1, 2, GET, GET, GET, 1, 2, GET, GET, GET }), + ((int []){ 1, 2, MISSING, 1, 2, MISSING })); +} + +void test_prio_queue__stack(void) +{ + TEST_INPUT(((int []){ STACK, 8, 1, 5, 4, 6, 2, 3, DUMP }), + ((int []){ 3, 2, 6, 4, 5, 1, 8 })); +} + +void test_prio_queue__reverse_stack(void) +{ + TEST_INPUT(((int []){ STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP }), + ((int []){ 1, 2, 3, 4, 5, 6 })); +} diff --git a/t/unit-tests/t-reftable-tree.c b/t/unit-tests/u-reftable-tree.c index 79b175a45a..bcf9061071 100644 --- a/t/unit-tests/t-reftable-tree.c +++ b/t/unit-tests/u-reftable-tree.c @@ -6,7 +6,7 @@ license that can be found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd */ -#include "test-lib.h" +#include "unit-test.h" #include "reftable/tree.h" static int t_compare(const void *a, const void *b) @@ -25,7 +25,7 @@ static void store(void *arg, void *key) c->arr[c->len++] = key; } -static void t_tree_search(void) +void test_reftable_tree__tree_search(void) { struct tree_node *root = NULL; void *values[11] = { 0 }; @@ -38,20 +38,20 @@ static void t_tree_search(void) */ do { nodes[i] = tree_insert(&root, &values[i], &t_compare); - check(nodes[i] != NULL); + cl_assert(nodes[i] != NULL); i = (i * 7) % 11; } while (i != 1); for (i = 1; i < ARRAY_SIZE(nodes); i++) { - check_pointer_eq(&values[i], nodes[i]->key); - check_pointer_eq(nodes[i], tree_search(root, &values[i], &t_compare)); + cl_assert_equal_p(&values[i], nodes[i]->key); + cl_assert_equal_p(nodes[i], tree_search(root, &values[i], &t_compare)); } - check(!tree_search(root, values, t_compare)); + cl_assert(tree_search(root, values, t_compare) == NULL); tree_free(root); } -static void t_infix_walk(void) +void test_reftable_tree__infix_walk(void) { struct tree_node *root = NULL; void *values[11] = { 0 }; @@ -64,23 +64,15 @@ static void t_infix_walk(void) do { struct tree_node *node = tree_insert(&root, &values[i], t_compare); - check(node != NULL); + cl_assert(node != NULL); i = (i * 7) % 11; count++; } while (i != 1); infix_walk(root, &store, &c); for (i = 1; i < ARRAY_SIZE(values); i++) - check_pointer_eq(&values[i], out[i - 1]); - check(!out[i - 1]); - check_int(c.len, ==, count); + cl_assert_equal_p(&values[i], out[i - 1]); + cl_assert(out[i - 1] == NULL); + cl_assert_equal_i(c.len, count); tree_free(root); } - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_tree_search(), "tree_search works"); - TEST(t_infix_walk(), "infix_walk works"); - - return test_done(); -} diff --git a/t/unit-tests/u-strbuf.c b/t/unit-tests/u-strbuf.c new file mode 100644 index 0000000000..caa5d78aa3 --- /dev/null +++ b/t/unit-tests/u-strbuf.c @@ -0,0 +1,119 @@ +#include "unit-test.h" +#include "strbuf.h" + +/* wrapper that supplies tests with an empty, initialized strbuf */ +static void setup(void (*f)(struct strbuf*, const void*), + const void *data) +{ + struct strbuf buf = STRBUF_INIT; + + f(&buf, data); + strbuf_release(&buf); + cl_assert_equal_i(buf.len, 0); + cl_assert_equal_i(buf.alloc, 0); +} + +/* wrapper that supplies tests with a populated, initialized strbuf */ +static void setup_populated(void (*f)(struct strbuf*, const void*), + const char *init_str, const void *data) +{ + struct strbuf buf = STRBUF_INIT; + + strbuf_addstr(&buf, init_str); + cl_assert_equal_i(buf.len, strlen(init_str)); + f(&buf, data); + strbuf_release(&buf); + cl_assert_equal_i(buf.len, 0); + cl_assert_equal_i(buf.alloc, 0); +} + +static void assert_sane_strbuf(struct strbuf *buf) +{ + /* Initialized strbufs should always have a non-NULL buffer */ + cl_assert(buf->buf != NULL); + /* Buffers should always be NUL-terminated */ + cl_assert(buf->buf[buf->len] == '\0'); + /* + * In case the buffer contains anything, `alloc` must alloc must + * be at least one byte larger than `len`. + */ + if (buf->len) + cl_assert(buf->len < buf->alloc); +} + +void test_strbuf__static_init(void) +{ + struct strbuf buf = STRBUF_INIT; + + cl_assert_equal_i(buf.len, 0); + cl_assert_equal_i(buf.alloc, 0); + cl_assert(buf.buf[0] == '\0'); +} + +void test_strbuf__dynamic_init(void) +{ + struct strbuf buf; + + strbuf_init(&buf, 1024); + assert_sane_strbuf(&buf); + cl_assert_equal_i(buf.len, 0); + cl_assert(buf.alloc >= 1024); + cl_assert(buf.buf[0] == '\0'); + strbuf_release(&buf); +} + +static void t_addch(struct strbuf *buf, const void *data) +{ + const char *p_ch = data; + const char ch = *p_ch; + size_t orig_alloc = buf->alloc; + size_t orig_len = buf->len; + + assert_sane_strbuf(buf); + strbuf_addch(buf, ch); + assert_sane_strbuf(buf); + cl_assert_equal_i(buf->len, orig_len + 1); + cl_assert(buf->alloc >= orig_alloc); + cl_assert(buf->buf[buf->len] == '\0'); +} + +static void t_addstr(struct strbuf *buf, const void *data) +{ + const char *text = data; + size_t len = strlen(text); + size_t orig_alloc = buf->alloc; + size_t orig_len = buf->len; + + assert_sane_strbuf(buf); + strbuf_addstr(buf, text); + assert_sane_strbuf(buf); + cl_assert_equal_i(buf->len, orig_len + len); + cl_assert(buf->alloc >= orig_alloc); + cl_assert(buf->buf[buf->len] == '\0'); + cl_assert_equal_s(buf->buf + orig_len, text); +} + +void test_strbuf__add_single_char(void) +{ + setup(t_addch, "a"); +} + +void test_strbuf__add_empty_char(void) +{ + setup(t_addch, ""); +} + +void test_strbuf__add_append_char(void) +{ + setup_populated(t_addch, "initial value", "a"); +} + +void test_strbuf__add_single_str(void) +{ + setup(t_addstr, "hello there"); +} + +void test_strbuf__add_append_str(void) +{ + setup_populated(t_addstr, "initial value", "hello there"); +} diff --git a/t/unit-tests/u-strcmp-offset.c b/t/unit-tests/u-strcmp-offset.c new file mode 100644 index 0000000000..7e8e9acf3c --- /dev/null +++ b/t/unit-tests/u-strcmp-offset.c @@ -0,0 +1,45 @@ +#include "unit-test.h" +#include "read-cache-ll.h" + +static void check_strcmp_offset(const char *string1, const char *string2, + int expect_result, uintmax_t expect_offset) +{ + size_t offset; + int result = strcmp_offset(string1, string2, &offset); + + /* + * Because different CRTs behave differently, only rely on signs of the + * result values. + */ + result = (result < 0 ? -1 : + result > 0 ? 1 : + 0); + + cl_assert_equal_i(result, expect_result); + cl_assert_equal_i((uintmax_t)offset, expect_offset); +} + +void test_strcmp_offset__empty(void) +{ + check_strcmp_offset("", "", 0, 0); +} + +void test_strcmp_offset__equal(void) +{ + check_strcmp_offset("abc", "abc", 0, 3); +} + +void test_strcmp_offset__different(void) +{ + check_strcmp_offset("abc", "def", -1, 0); +} + +void test_strcmp_offset__mismatch(void) +{ + check_strcmp_offset("abc", "abz", -1, 2); +} + +void test_strcmp_offset__different_length(void) +{ + check_strcmp_offset("abc", "abcdef", -1, 3); +} diff --git a/t/unit-tests/unit-test.c b/t/unit-tests/unit-test.c index fa8818842a..5af645048a 100644 --- a/t/unit-tests/unit-test.c +++ b/t/unit-tests/unit-test.c @@ -1,5 +1,7 @@ #include "unit-test.h" +#include "hex.h" #include "parse-options.h" +#include "strbuf.h" #include "string-list.h" #include "strvec.h" diff --git a/tempfile.c b/tempfile.c index ed88cf8431..82dfa3d82f 100644 --- a/tempfile.c +++ b/tempfile.c @@ -42,6 +42,8 @@ * file created by its parent. */ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "abspath.h" #include "path.h" @@ -148,7 +150,7 @@ struct tempfile *create_tempfile_mode(const char *path, int mode) return NULL; } activate_tempfile(tempfile); - if (adjust_shared_perm(tempfile->filename.buf)) { + if (adjust_shared_perm(the_repository, tempfile->filename.buf)) { int save_errno = errno; error("cannot fix permission bits on %s", tempfile->filename.buf); delete_tempfile(&tempfile); diff --git a/templates/Makefile b/templates/Makefile index bd1e9e30c1..722755338d 100644 --- a/templates/Makefile +++ b/templates/Makefile @@ -1,3 +1,6 @@ +# The default target of this Makefile is... +all:: + # Import tree-wide shared Makefile behavior and libraries include ../shared.mak @@ -23,7 +26,7 @@ PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) template_instdir_SQ = $(subst ','\'',$(template_instdir)) -all: boilerplates.made custom +all:: boilerplates.made custom # Put templates that can be copied straight from the source # in a file direc--tory--file in the source. They will be diff --git a/tmp-objdir.c b/tmp-objdir.c index 659fcdcc29..31d16a4c2c 100644 --- a/tmp-objdir.c +++ b/tmp-objdir.c @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "tmp-objdir.h" #include "abspath.h" @@ -16,6 +14,7 @@ #include "repository.h" struct tmp_objdir { + struct repository *repo; struct strbuf path; struct strvec env; struct object_directory *prev_odb; @@ -116,7 +115,8 @@ static int setup_tmp_objdir(const char *root) return ret; } -struct tmp_objdir *tmp_objdir_create(const char *prefix) +struct tmp_objdir *tmp_objdir_create(struct repository *r, + const char *prefix) { static int installed_handlers; struct tmp_objdir *t; @@ -125,6 +125,7 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix) BUG("only one tmp_objdir can be used at a time"); t = xcalloc(1, sizeof(*t)); + t->repo = r; strbuf_init(&t->path, 0); strvec_init(&t->env); @@ -134,7 +135,7 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix) * them. */ strbuf_addf(&t->path, "%s/tmp_objdir-%s-XXXXXX", - repo_get_object_directory(the_repository), prefix); + repo_get_object_directory(r), prefix); if (!mkdtemp(t->path.buf)) { /* free, not destroy, as we never touched the filesystem */ @@ -154,7 +155,7 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix) } env_append(&t->env, ALTERNATE_DB_ENVIRONMENT, - absolute_path(repo_get_object_directory(the_repository))); + absolute_path(repo_get_object_directory(r))); env_replace(&t->env, DB_ENVIRONMENT, absolute_path(t->path.buf)); env_replace(&t->env, GIT_QUARANTINE_ENVIRONMENT, absolute_path(t->path.buf)); @@ -206,10 +207,12 @@ static int read_dir_paths(struct string_list *out, const char *path) return 0; } -static int migrate_paths(struct strbuf *src, struct strbuf *dst, +static int migrate_paths(struct tmp_objdir *t, + struct strbuf *src, struct strbuf *dst, enum finalize_object_file_flags flags); -static int migrate_one(struct strbuf *src, struct strbuf *dst, +static int migrate_one(struct tmp_objdir *t, + struct strbuf *src, struct strbuf *dst, enum finalize_object_file_flags flags) { struct stat st; @@ -218,11 +221,11 @@ static int migrate_one(struct strbuf *src, struct strbuf *dst, return -1; if (S_ISDIR(st.st_mode)) { if (!mkdir(dst->buf, 0777)) { - if (adjust_shared_perm(dst->buf)) + if (adjust_shared_perm(t->repo, dst->buf)) return -1; } else if (errno != EEXIST) return -1; - return migrate_paths(src, dst, flags); + return migrate_paths(t, src, dst, flags); } return finalize_object_file_flags(src->buf, dst->buf, flags); } @@ -232,7 +235,8 @@ static int is_loose_object_shard(const char *name) return strlen(name) == 2 && isxdigit(name[0]) && isxdigit(name[1]); } -static int migrate_paths(struct strbuf *src, struct strbuf *dst, +static int migrate_paths(struct tmp_objdir *t, + struct strbuf *src, struct strbuf *dst, enum finalize_object_file_flags flags) { size_t src_len = src->len, dst_len = dst->len; @@ -254,7 +258,7 @@ static int migrate_paths(struct strbuf *src, struct strbuf *dst, if (is_loose_object_shard(name)) flags_copy |= FOF_SKIP_COLLISION_CHECK; - ret |= migrate_one(src, dst, flags_copy); + ret |= migrate_one(t, src, dst, flags_copy); strbuf_setlen(src, src_len); strbuf_setlen(dst, dst_len); @@ -273,16 +277,16 @@ int tmp_objdir_migrate(struct tmp_objdir *t) return 0; if (t->prev_odb) { - if (the_repository->objects->odb->will_destroy) + if (t->repo->objects->odb->will_destroy) BUG("migrating an ODB that was marked for destruction"); restore_primary_odb(t->prev_odb, t->path.buf); t->prev_odb = NULL; } strbuf_addbuf(&src, &t->path); - strbuf_addstr(&dst, repo_get_object_directory(the_repository)); + strbuf_addstr(&dst, repo_get_object_directory(t->repo)); - ret = migrate_paths(&src, &dst, 0); + ret = migrate_paths(t, &src, &dst, 0); strbuf_release(&src); strbuf_release(&dst); diff --git a/tmp-objdir.h b/tmp-objdir.h index 237d96b660..fceda14979 100644 --- a/tmp-objdir.h +++ b/tmp-objdir.h @@ -11,7 +11,7 @@ * Example: * * struct child_process child = CHILD_PROCESS_INIT; - * struct tmp_objdir *t = tmp_objdir_create("incoming"); + * struct tmp_objdir *t = tmp_objdir_create(repo, "incoming"); * strvec_push(&child.args, cmd); * strvec_pushv(&child.env, tmp_objdir_env(t)); * if (!run_command(&child)) && !tmp_objdir_migrate(t)) @@ -21,13 +21,14 @@ * */ +struct repository; struct tmp_objdir; /* * Create a new temporary object directory with the specified prefix; * returns NULL on failure. */ -struct tmp_objdir *tmp_objdir_create(const char *prefix); +struct tmp_objdir *tmp_objdir_create(struct repository *r, const char *prefix); /* * Return a list of environment strings, suitable for use with @@ -21,7 +21,6 @@ * along with this program; if not, see <https://www.gnu.org/licenses/>. */ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -298,7 +297,7 @@ static const char *quote_crnl(const char *path) return new_path.buf; } -void trace_repo_setup(void) +void trace_repo_setup(struct repository *r) { const char *git_work_tree, *prefix = startup_info->prefix; char *cwd; @@ -308,14 +307,14 @@ void trace_repo_setup(void) cwd = xgetcwd(); - if (!(git_work_tree = repo_get_work_tree(the_repository))) + if (!(git_work_tree = repo_get_work_tree(r))) git_work_tree = "(null)"; if (!startup_info->prefix) prefix = "(null)"; - trace_printf_key(&trace_setup_key, "setup: git_dir: %s\n", quote_crnl(repo_get_git_dir(the_repository))); - trace_printf_key(&trace_setup_key, "setup: git_common_dir: %s\n", quote_crnl(repo_get_common_dir(the_repository))); + trace_printf_key(&trace_setup_key, "setup: git_dir: %s\n", quote_crnl(repo_get_git_dir(r))); + trace_printf_key(&trace_setup_key, "setup: git_common_dir: %s\n", quote_crnl(repo_get_common_dir(r))); trace_printf_key(&trace_setup_key, "setup: worktree: %s\n", quote_crnl(git_work_tree)); trace_printf_key(&trace_setup_key, "setup: cwd: %s\n", quote_crnl(cwd)); trace_printf_key(&trace_setup_key, "setup: prefix: %s\n", quote_crnl(prefix)); @@ -92,7 +92,9 @@ extern struct trace_key trace_default_key; extern struct trace_key trace_perf_key; extern struct trace_key trace_setup_key; -void trace_repo_setup(void); +struct repository; + +void trace_repo_setup(struct repository *r); /** * Checks whether the trace key is enabled. Used to prevent expensive @@ -764,7 +764,7 @@ void trace2_def_param_fl(const char *file, int line, const char *param, if (!trace2_enabled) return; - redacted = redact_arg(value); + redacted = value ? redact_arg(value) : NULL; for_each_wanted_builtin (j, tgt_j) if (tgt_j->pfn_param_fl) @@ -31,7 +31,7 @@ * * For more info about: trace2 targets, conventions for public functions and * macros, trace2 target formats and examples on trace2 API usage refer to - * Documentation/technical/api-trace2.txt + * Documentation/technical/api-trace2.adoc * */ diff --git a/trace2/tr2_sid.c b/trace2/tr2_sid.c index 09c4ef0d17..1c1d27b0ee 100644 --- a/trace2/tr2_sid.c +++ b/trace2/tr2_sid.c @@ -32,7 +32,7 @@ static void tr2_sid_append_my_sid_component(void) { const struct git_hash_algo *algo = &hash_algos[GIT_HASH_SHA1]; struct tr2_tbuf tb_now; - git_hash_ctx ctx; + struct git_hash_ctx ctx; pid_t pid = getpid(); unsigned char hash[GIT_MAX_RAWSZ + 1]; char hex[GIT_MAX_HEXSZ + 1]; @@ -46,8 +46,8 @@ static void tr2_sid_append_my_sid_component(void) strbuf_add(&tr2sid_buf, "Localhost", 9); else { algo->init_fn(&ctx); - algo->update_fn(&ctx, hostname, strlen(hostname)); - algo->final_fn(hash, &ctx); + git_hash_update(&ctx, hostname, strlen(hostname)); + git_hash_final(hash, &ctx); hash_to_hex_algop_r(hex, hash, algo); strbuf_addch(&tr2sid_buf, 'H'); strbuf_add(&tr2sid_buf, hex, 8); diff --git a/trace2/tr2_sysenv.c b/trace2/tr2_sysenv.c index 01379c5cad..4abc218514 100644 --- a/trace2/tr2_sysenv.c +++ b/trace2/tr2_sysenv.c @@ -7,7 +7,7 @@ /* * Each entry represents a trace2 setting. - * See Documentation/technical/api-trace2.txt + * See Documentation/technical/api-trace2.adoc */ struct tr2_sysenv_entry { const char *env_var_name; diff --git a/trace2/tr2_tgt_event.c b/trace2/tr2_tgt_event.c index 69ee40449f..5a0381791f 100644 --- a/trace2/tr2_tgt_event.c +++ b/trace2/tr2_tgt_event.c @@ -493,7 +493,8 @@ static void fn_param_fl(const char *file, int line, const char *param, event_fmt_prepare(event_name, file, line, NULL, &jw); jw_object_string(&jw, "scope", scope_name); jw_object_string(&jw, "param", param); - jw_object_string(&jw, "value", value); + if (value) + jw_object_string(&jw, "value", value); jw_end(&jw); tr2_dst_write_line(&tr2dst_event, &jw.json); diff --git a/trace2/tr2_tgt_normal.c b/trace2/tr2_tgt_normal.c index baef48aa69..924736ab36 100644 --- a/trace2/tr2_tgt_normal.c +++ b/trace2/tr2_tgt_normal.c @@ -307,8 +307,9 @@ static void fn_param_fl(const char *file, int line, const char *param, enum config_scope scope = kvi->scope; const char *scope_name = config_scope_name(scope); - strbuf_addf(&buf_payload, "def_param scope:%s %s=%s", scope_name, param, - value); + strbuf_addf(&buf_payload, "def_param scope:%s %s", scope_name, param); + if (value) + strbuf_addf(&buf_payload, "=%s", value); normal_io_write_fl(file, line, &buf_payload); strbuf_release(&buf_payload); } diff --git a/trace2/tr2_tgt_perf.c b/trace2/tr2_tgt_perf.c index 298ae27f9d..4eb9289f95 100644 --- a/trace2/tr2_tgt_perf.c +++ b/trace2/tr2_tgt_perf.c @@ -448,8 +448,9 @@ static void fn_param_fl(const char *file, int line, const char *param, struct strbuf scope_payload = STRBUF_INIT; enum config_scope scope = kvi->scope; const char *scope_name = config_scope_name(scope); - - strbuf_addf(&buf_payload, "%s:%s", param, value); + strbuf_addstr(&buf_payload, param); + if (value) + strbuf_addf(&buf_payload, ":%s", value); strbuf_addf(&scope_payload, "%s:%s", "scope", scope_name); perf_io_write_fl(file, line, event_name, NULL, NULL, NULL, diff --git a/transport.c b/transport.c index 10d820c333..6c2801bcbd 100644 --- a/transport.c +++ b/transport.c @@ -207,6 +207,7 @@ static int fetch_refs_from_bundle(struct transport *transport, ret = unbundle(the_repository, &data->header, data->fd, &extra_index_pack_args, &opts); + data->fd = -1; /* `unbundle()` closes the file descriptor */ transport->hash_algo = data->header.hash_algo; strvec_clear(&extra_index_pack_args); @@ -932,8 +933,15 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re break; case protocol_v1: case protocol_v0: - ret = send_pack(&args, data->fd, data->conn, remote_refs, + ret = send_pack(the_repository, &args, data->fd, data->conn, remote_refs, &data->extra_have); + /* + * Ignore the specific error code to maintain consistent behavior + * with the "push_refs()" function across different transports, + * such as "push_refs_with_push()" for HTTP protocol. + */ + if (ret == ERROR_SEND_PACK_BAD_REF_STATUS) + ret = 0; break; case protocol_unknown_version: BUG("unknown protocol version"); @@ -941,15 +949,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re close(data->fd[1]); close(data->fd[0]); - /* - * Atomic push may abort the connection early and close the pipe, - * which may cause an error for `finish_connect()`. Ignore this error - * for atomic git-push. - */ - if (ret || args.atomic) - finish_connect(data->conn); - else - ret = finish_connect(data->conn); + ret |= finish_connect(data->conn); data->conn = NULL; data->finished_handshake = 0; diff --git a/transport.h b/transport.h index 44100fa9b7..892f19454a 100644 --- a/transport.h +++ b/transport.h @@ -168,7 +168,7 @@ struct transport *transport_get(struct remote *, const char *); * Check whether a transport is allowed by the environment. * * Type should generally be the URL scheme, as described in - * Documentation/git.txt + * Documentation/git.adoc * * from_user specifies if the transport was given by the user. If unknown pass * a -1 to read from the environment to determine if the transport was given by diff --git a/tree-diff.c b/tree-diff.c index d9237ffd9b..60c558c2b5 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -48,8 +48,8 @@ free((x)); \ } while(0) -static struct combine_diff_path *ll_diff_tree_paths( - struct combine_diff_path *p, const struct object_id *oid, +static void ll_diff_tree_paths( + struct combine_diff_path ***tail, const struct object_id *oid, const struct object_id **parents_oid, int nparent, struct strbuf *base, struct diff_options *opt, int depth); @@ -125,72 +125,6 @@ static int emit_diff_first_parent_only(struct diff_options *opt, struct combine_ /* - * Make a new combine_diff_path from path/mode/sha1 - * and append it to paths list tail. - * - * Memory for created elements could be reused: - * - * - if last->next == NULL, the memory is allocated; - * - * - if last->next != NULL, it is assumed that p=last->next was returned - * earlier by this function, and p->next was *not* modified. - * The memory is then reused from p. - * - * so for clients, - * - * - if you do need to keep the element - * - * p = path_appendnew(p, ...); - * process(p); - * p->next = NULL; - * - * - if you don't need to keep the element after processing - * - * pprev = p; - * p = path_appendnew(p, ...); - * process(p); - * p = pprev; - * ; don't forget to free tail->next in the end - * - * p->parent[] remains uninitialized. - */ -static struct combine_diff_path *path_appendnew(struct combine_diff_path *last, - int nparent, const struct strbuf *base, const char *path, int pathlen, - unsigned mode, const struct object_id *oid) -{ - struct combine_diff_path *p; - size_t len = st_add(base->len, pathlen); - size_t alloclen = combine_diff_path_size(nparent, len); - - /* if last->next is !NULL - it is a pre-allocated memory, we can reuse */ - p = last->next; - if (p && (alloclen > (intptr_t)p->next)) { - FREE_AND_NULL(p); - } - - if (!p) { - p = xmalloc(alloclen); - - /* - * until we go to it next round, .next holds how many bytes we - * allocated (for faster realloc - we don't need copying old data). - */ - p->next = (struct combine_diff_path *)(intptr_t)alloclen; - } - - last->next = p; - - p->path = (char *)&(p->parent[nparent]); - memcpy(p->path, base->buf, base->len); - memcpy(p->path + base->len, path, pathlen); - p->path[len] = 0; - p->mode = mode; - oidcpy(&p->oid, oid ? oid : null_oid()); - - return p; -} - -/* * new path should be added to combine diff * * 3 cases on how/when it should be called and behaves: @@ -200,10 +134,10 @@ static struct combine_diff_path *path_appendnew(struct combine_diff_path *last, * t, tp -> path modified/added * (M for tp[i]=tp[imin], A otherwise) */ -static struct combine_diff_path *emit_path(struct combine_diff_path *p, - struct strbuf *base, struct diff_options *opt, int nparent, - struct tree_desc *t, struct tree_desc *tp, - int imin, int depth) +static void emit_path(struct combine_diff_path ***tail, + struct strbuf *base, struct diff_options *opt, + int nparent, struct tree_desc *t, struct tree_desc *tp, + int imin, int depth) { unsigned short mode; const char *path; @@ -243,8 +177,13 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p, if (emitthis) { int keep; - struct combine_diff_path *pprev = p; - p = path_appendnew(p, nparent, base, path, pathlen, mode, oid); + struct combine_diff_path *p; + + strbuf_add(base, path, pathlen); + p = combine_diff_path_new(base->buf, base->len, mode, + oid ? oid : null_oid(), + nparent); + strbuf_setlen(base, old_baselen); for (i = 0; i < nparent; ++i) { /* @@ -279,21 +218,12 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p, if (opt->pathchange) keep = opt->pathchange(opt, p); - /* - * If a path was filtered or consumed - we don't need to add it - * to the list and can reuse its memory, leaving it as - * pre-allocated element on the tail. - * - * On the other hand, if path needs to be kept, we need to - * correct its .next to NULL, as it was pre-initialized to how - * much memory was allocated. - * - * see path_appendnew() for details. - */ - if (!keep) - p = pprev; - else - p->next = NULL; + if (keep) { + **tail = p; + *tail = &p->next; + } else { + free(p); + } } if (recurse) { @@ -309,13 +239,12 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p, strbuf_add(base, path, pathlen); strbuf_addch(base, '/'); - p = ll_diff_tree_paths(p, oid, parents_oid, nparent, base, opt, - depth + 1); + ll_diff_tree_paths(tail, oid, parents_oid, nparent, base, opt, + depth + 1); FAST_ARRAY_FREE(parents_oid, nparent); } strbuf_setlen(base, old_baselen); - return p; } static void skip_uninteresting(struct tree_desc *t, struct strbuf *base, @@ -428,8 +357,8 @@ static inline void update_tp_entries(struct tree_desc *tp, int nparent) update_tree_entry(&tp[i]); } -static struct combine_diff_path *ll_diff_tree_paths( - struct combine_diff_path *p, const struct object_id *oid, +static void ll_diff_tree_paths( + struct combine_diff_path ***tail, const struct object_id *oid, const struct object_id **parents_oid, int nparent, struct strbuf *base, struct diff_options *opt, int depth) @@ -533,8 +462,8 @@ static struct combine_diff_path *ll_diff_tree_paths( } /* D += {δ(t,pi) if pi=p[imin]; "+a" if pi > p[imin]} */ - p = emit_path(p, base, opt, nparent, - &t, tp, imin, depth); + emit_path(tail, base, opt, nparent, + &t, tp, imin, depth); skip_emit_t_tp: /* t↓, ∀ pi=p[imin] pi↓ */ @@ -545,8 +474,8 @@ static struct combine_diff_path *ll_diff_tree_paths( /* t < p[imin] */ else if (cmp < 0) { /* D += "+t" */ - p = emit_path(p, base, opt, nparent, - &t, /*tp=*/NULL, -1, depth); + emit_path(tail, base, opt, nparent, + &t, /*tp=*/NULL, -1, depth); /* t↓ */ update_tree_entry(&t); @@ -561,8 +490,8 @@ static struct combine_diff_path *ll_diff_tree_paths( goto skip_emit_tp; } - p = emit_path(p, base, opt, nparent, - /*t=*/NULL, tp, imin, depth); + emit_path(tail, base, opt, nparent, + /*t=*/NULL, tp, imin, depth); skip_emit_tp: /* ∀ pi=p[imin] pi↓ */ @@ -575,24 +504,16 @@ static struct combine_diff_path *ll_diff_tree_paths( free(tptree[i]); FAST_ARRAY_FREE(tptree, nparent); FAST_ARRAY_FREE(tp, nparent); - - return p; } struct combine_diff_path *diff_tree_paths( - struct combine_diff_path *p, const struct object_id *oid, + const struct object_id *oid, const struct object_id **parents_oid, int nparent, struct strbuf *base, struct diff_options *opt) { - p = ll_diff_tree_paths(p, oid, parents_oid, nparent, base, opt, 0); - - /* - * free pre-allocated last element, if any - * (see path_appendnew() for details about why) - */ - FREE_AND_NULL(p->next); - - return p; + struct combine_diff_path *head = NULL, **tail = &head; + ll_diff_tree_paths(&tail, oid, parents_oid, nparent, base, opt, 0); + return head; } /* @@ -708,14 +629,13 @@ static void ll_diff_tree_oid(const struct object_id *old_oid, const struct object_id *new_oid, struct strbuf *base, struct diff_options *opt) { - struct combine_diff_path phead, *p; + struct combine_diff_path *paths, *p; pathchange_fn_t pathchange_old = opt->pathchange; - phead.next = NULL; opt->pathchange = emit_diff_first_parent_only; - diff_tree_paths(&phead, new_oid, &old_oid, 1, base, opt); + paths = diff_tree_paths(new_oid, &old_oid, 1, base, opt); - for (p = phead.next; p;) { + for (p = paths; p;) { struct combine_diff_path *pprev = p; p = p->next; free(pprev); diff --git a/unix-socket.c b/unix-socket.c index 483c9c448c..8860203c3f 100644 --- a/unix-socket.c +++ b/unix-socket.c @@ -65,8 +65,10 @@ static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path, if (strbuf_getcwd(&cwd)) return -1; ctx->orig_dir = strbuf_detach(&cwd, NULL); - if (chdir_len(dir, slash - dir) < 0) + if (chdir_len(dir, slash - dir) < 0) { + FREE_AND_NULL(ctx->orig_dir); return -1; + } } memset(sa, 0, sizeof(*sa)); diff --git a/unpack-trees.c b/unpack-trees.c index b3be5d542f..cf5b73c84b 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -372,7 +372,8 @@ static struct progress *get_progress(struct unpack_trees_options *o, total++; } - return start_delayed_progress(_("Updating files"), total); + return start_delayed_progress(the_repository, + _("Updating files"), total); } static void setup_collided_checkout_detection(struct checkout *state, @@ -1773,6 +1774,7 @@ static int clear_ce_flags(struct index_state *istate, strbuf_reset(&prefix); if (show_progress) istate->progress = start_delayed_progress( + the_repository, _("Updating index flags"), istate->cache_nr); @@ -2902,7 +2904,7 @@ int threeway_merge(const struct cache_entry * const *stages, * The rule is to "carry forward" what is in the index without losing * information across a "fast-forward", favoring a successful merge * over a merge failure when it makes sense. For details of the - * "carry forward" rule, please see <Documentation/git-read-tree.txt>. + * "carry forward" rule, please see <Documentation/git-read-tree.adoc>. * */ int twoway_merge(const struct cache_entry * const *src, diff --git a/upload-pack.c b/upload-pack.c index 728b2477fc..7498b45e2e 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -32,6 +32,7 @@ #include "write-or-die.h" #include "json-writer.h" #include "strmap.h" +#include "promisor-remote.h" /* Remember to update object flag allocation in object.h */ #define THEY_HAVE (1u << 11) @@ -319,6 +320,8 @@ static void create_pack_file(struct upload_pack_data *pack_data, strvec_push(&pack_objects.args, "--delta-base-offset"); if (pack_data->use_include_tag) strvec_push(&pack_objects.args, "--include-tag"); + if (repo_has_accepted_promisor_remote(the_repository)) + strvec_push(&pack_objects.args, "--missing=allow-promisor"); if (pack_data->filter_options.choice) { const char *spec = expand_list_objects_filter_spec(&pack_data->filter_options); @@ -8,7 +8,7 @@ #include "gettext.h" #include "trace2.h" -static void vreportf(const char *prefix, const char *err, va_list params) +static void vfreportf(FILE *f, const char *prefix, const char *err, va_list params) { char msg[4096]; char *p, *pend = msg + sizeof(msg); @@ -32,8 +32,13 @@ static void vreportf(const char *prefix, const char *err, va_list params) } *(p++) = '\n'; /* we no longer need a NUL */ - fflush(stderr); - write_in_full(2, msg, p - msg); + fflush(f); + write_in_full(fileno(f), msg, p - msg); +} + +static void vreportf(const char *prefix, const char *err, va_list params) +{ + vfreportf(stderr, prefix, err, params); } static NORETURN void usage_builtin(const char *err, va_list params) @@ -173,6 +178,22 @@ void NORETURN usage(const char *err) usagef("%s", err); } +static void show_usage_if_asked_helper(const char *err, ...) +{ + va_list params; + + va_start(params, err); + vfreportf(stdout, _("usage: "), err, params); + va_end(params); + exit(129); +} + +void show_usage_if_asked(int ac, const char **av, const char *err) +{ + if (ac == 2 && !strcmp(av[1], "-h")) + show_usage_if_asked_helper(err); +} + void NORETURN die(const char *err, ...) { va_list params; @@ -1,11 +1,32 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "version.h" -#include "version-def.h" #include "strbuf.h" +#include "gettext.h" + +#ifndef GIT_VERSION_H +# include "version-def.h" +#else +# include GIT_VERSION_H +#endif const char git_version_string[] = GIT_VERSION; const char git_built_from_commit_string[] = GIT_BUILT_FROM_COMMIT; +/* + * Trim and replace each character with ascii code below 32 or above + * 127 (included) using a dot '.' character. + */ +static void redact_non_printables(struct strbuf *buf) +{ + strbuf_trim(buf); + for (size_t i = 0; i < buf->len; i++) { + if (!isprint(buf->buf[i]) || buf->buf[i] == ' ') + buf->buf[i] = '.'; + } +} + const char *git_user_agent(void) { static const char *agent = NULL; @@ -19,6 +40,27 @@ const char *git_user_agent(void) return agent; } +/* + Retrieve, sanitize and cache operating system info for subsequent + calls. Return a pointer to the sanitized operating system info + string. +*/ +static const char *os_info(void) +{ + static const char *os = NULL; + + if (!os) { + struct strbuf buf = STRBUF_INIT; + + get_uname_info(&buf, 0); + /* Sanitize the os information immediately */ + redact_non_printables(&buf); + os = strbuf_detach(&buf, NULL); + } + + return os; +} + const char *git_user_agent_sanitized(void) { static const char *agent = NULL; @@ -27,13 +69,35 @@ const char *git_user_agent_sanitized(void) struct strbuf buf = STRBUF_INIT; strbuf_addstr(&buf, git_user_agent()); - strbuf_trim(&buf); - for (size_t i = 0; i < buf.len; i++) { - if (buf.buf[i] <= 32 || buf.buf[i] >= 127) - buf.buf[i] = '.'; + + if (!getenv("GIT_USER_AGENT")) { + strbuf_addch(&buf, '-'); + strbuf_addstr(&buf, os_info()); } - agent = buf.buf; + redact_non_printables(&buf); + agent = strbuf_detach(&buf, NULL); } return agent; } + +int get_uname_info(struct strbuf *buf, unsigned int full) +{ + struct utsname uname_info; + + if (uname(&uname_info)) { + strbuf_addf(buf, _("uname() failed with error '%s' (%d)\n"), + strerror(errno), + errno); + return -1; + } + if (full) + strbuf_addf(buf, "%s %s %s %s\n", + uname_info.sysname, + uname_info.release, + uname_info.version, + uname_info.machine); + else + strbuf_addf(buf, "%s\n", uname_info.sysname); + return 0; +} @@ -1,10 +1,20 @@ #ifndef VERSION_H #define VERSION_H +struct repository; + extern const char git_version_string[]; extern const char git_built_from_commit_string[]; const char *git_user_agent(void); const char *git_user_agent_sanitized(void); +/* + Try to get information about the system using uname(2). + Return -1 and put an error message into 'buf' in case of uname() + error. Return 0 and put uname info into 'buf' otherwise. +*/ +int get_uname_info(struct strbuf *buf, unsigned int full); + + #endif /* VERSION_H */ @@ -172,7 +172,8 @@ static int loop(struct walker *walker) uint64_t nr = 0; if (walker->get_progress) - progress = start_delayed_progress(_("Fetching objects"), 0); + progress = start_delayed_progress(the_repository, + _("Fetching objects"), 0); while (process_queue) { struct object *obj = process_queue->item; diff --git a/worktree.c b/worktree.c index 248bbb39d4..c34b9eb74e 100644 --- a/worktree.c +++ b/worktree.c @@ -59,12 +59,35 @@ static void add_head_info(struct worktree *wt) static int is_current_worktree(struct worktree *wt) { char *git_dir = absolute_pathdup(repo_get_git_dir(the_repository)); - const char *wt_git_dir = get_worktree_git_dir(wt); + char *wt_git_dir = get_worktree_git_dir(wt); int is_current = !fspathcmp(git_dir, absolute_path(wt_git_dir)); + free(wt_git_dir); free(git_dir); return is_current; } +/* +* When in a secondary worktree, and when extensions.worktreeConfig +* is true, only $commondir/config and $commondir/worktrees/<id>/ +* config.worktree are consulted, hence any core.bare=true setting in +* $commondir/config.worktree gets overlooked. Thus, check it manually +* to determine if the repository is bare. +*/ +static int is_main_worktree_bare(struct repository *repo) +{ + int bare = 0; + struct config_set cs = {0}; + char *worktree_config = xstrfmt("%s/config.worktree", repo_get_common_dir(repo)); + + git_configset_init(&cs); + git_configset_add_file(&cs, worktree_config); + git_configset_get_bool(&cs, "core.bare", &bare); + + git_configset_clear(&cs); + free(worktree_config); + return bare; +} + /** * get the main worktree */ @@ -79,16 +102,17 @@ static struct worktree *get_main_worktree(int skip_reading_head) CALLOC_ARRAY(worktree, 1); worktree->repo = the_repository; worktree->path = strbuf_detach(&worktree_path, NULL); - /* - * NEEDSWORK: If this function is called from a secondary worktree and - * config.worktree is present, is_bare_repository_cfg will reflect the - * contents of config.worktree, not the contents of the main worktree. - * This means that worktree->is_bare may be set to 0 even if the main - * worktree is configured to be bare. - */ - worktree->is_bare = (is_bare_repository_cfg == 1) || - is_bare_repository(); worktree->is_current = is_current_worktree(worktree); + worktree->is_bare = (is_bare_repository_cfg == 1) || + is_bare_repository() || + /* + * When in a secondary worktree we have to also verify if the main + * worktree is bare in $commondir/config.worktree. + * This check is unnecessary if we're currently in the main worktree, + * as prior checks already consulted all configs of the current worktree. + */ + (!worktree->is_current && is_main_worktree_bare(the_repository)); + if (!skip_reading_head) add_head_info(worktree); return worktree; @@ -104,7 +128,7 @@ struct worktree *get_linked_worktree(const char *id, if (!id) die("Missing linked worktree name"); - strbuf_git_common_path(&path, the_repository, "worktrees/%s/gitdir", id); + repo_common_path_append(the_repository, &path, "worktrees/%s/gitdir", id); if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0) /* invalid gitdir file */ goto done; @@ -175,14 +199,19 @@ struct worktree **get_worktrees(void) return get_worktrees_internal(0); } -const char *get_worktree_git_dir(const struct worktree *wt) +struct worktree **get_worktrees_without_reading_head(void) +{ + return get_worktrees_internal(1); +} + +char *get_worktree_git_dir(const struct worktree *wt) { if (!wt) - return repo_get_git_dir(the_repository); + return xstrdup(repo_get_git_dir(the_repository)); else if (!wt->id) - return repo_get_common_dir(the_repository); + return xstrdup(repo_get_common_dir(the_repository)); else - return git_common_path("worktrees/%s", wt->id); + return repo_common_path(the_repository, "worktrees/%s", wt->id); } static struct worktree *find_worktree_by_suffix(struct worktree **list, @@ -313,6 +342,7 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, { struct strbuf wt_path = STRBUF_INIT; struct strbuf realpath = STRBUF_INIT; + struct strbuf buf = STRBUF_INIT; char *path = NULL; int err, ret = -1; @@ -342,7 +372,7 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, if (!is_absolute_path(wt->path)) { strbuf_addf_gently(errmsg, _("'%s' file does not contain absolute path to the working tree location"), - git_common_path("worktrees/%s/gitdir", wt->id)); + repo_common_path_replace(the_repository, &buf, "worktrees/%s/gitdir", wt->id)); goto done; } @@ -364,14 +394,16 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, goto done; } - strbuf_realpath(&realpath, git_common_path("worktrees/%s", wt->id), 1); + strbuf_realpath(&realpath, repo_common_path_replace(the_repository, &buf, "worktrees/%s", wt->id), 1); ret = fspathcmp(path, realpath.buf); if (ret) strbuf_addf_gently(errmsg, _("'%s' does not point back to '%s'"), - wt->path, git_common_path("worktrees/%s", wt->id)); + wt->path, repo_common_path_replace(the_repository, &buf, + "worktrees/%s", wt->id)); done: free(path); + strbuf_release(&buf); strbuf_release(&wt_path); strbuf_release(&realpath); return ret; @@ -383,11 +415,13 @@ void update_worktree_location(struct worktree *wt, const char *path_, struct strbuf path = STRBUF_INIT; struct strbuf dotgit = STRBUF_INIT; struct strbuf gitdir = STRBUF_INIT; + char *wt_gitdir; if (is_main_worktree(wt)) BUG("can't relocate main worktree"); - strbuf_realpath(&gitdir, git_common_path("worktrees/%s/gitdir", wt->id), 1); + wt_gitdir = repo_common_path(the_repository, "worktrees/%s/gitdir", wt->id); + strbuf_realpath(&gitdir, wt_gitdir, 1); strbuf_realpath(&path, path_, 1); strbuf_addf(&dotgit, "%s/.git", path.buf); if (fspathcmp(wt->path, path.buf)) { @@ -399,6 +433,7 @@ void update_worktree_location(struct worktree *wt, const char *path_, strbuf_release(&path); strbuf_release(&dotgit); strbuf_release(&gitdir); + free(wt_gitdir); } int is_worktree_being_rebased(const struct worktree *wt, @@ -487,7 +522,8 @@ int submodule_uses_worktrees(const char *path) int ret = 0; struct repository_format format = REPOSITORY_FORMAT_INIT; - submodule_gitdir = git_pathdup_submodule(path, "%s", ""); + submodule_gitdir = repo_submodule_path(the_repository, + path, "%s", ""); if (!submodule_gitdir) return 0; @@ -583,6 +619,7 @@ static void repair_gitfile(struct worktree *wt, struct strbuf backlink = STRBUF_INIT; char *dotgit_contents = NULL; const char *repair = NULL; + char *path = NULL; int err; /* missing worktree can't be repaired */ @@ -594,7 +631,8 @@ static void repair_gitfile(struct worktree *wt, goto done; } - strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1); + path = repo_common_path(the_repository, "worktrees/%s", wt->id); + strbuf_realpath(&repo, path, 1); strbuf_addf(&dotgit, "%s/.git", wt->path); strbuf_addf(&gitdir, "%s/gitdir", repo.buf); dotgit_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); @@ -624,6 +662,7 @@ static void repair_gitfile(struct worktree *wt, done: free(dotgit_contents); + free(path); strbuf_release(&repo); strbuf_release(&dotgit); strbuf_release(&gitdir); @@ -655,11 +694,13 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path struct strbuf gitdir = STRBUF_INIT; struct strbuf dotgit = STRBUF_INIT; int is_relative_path; + char *path = NULL; if (is_main_worktree(wt)) goto done; - strbuf_realpath(&gitdir, git_common_path("worktrees/%s/gitdir", wt->id), 1); + path = repo_common_path(the_repository, "worktrees/%s/gitdir", wt->id); + strbuf_realpath(&gitdir, path, 1); if (strbuf_read_file(&dotgit, gitdir.buf, 0) < 0) goto done; @@ -678,6 +719,7 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path done: strbuf_release(&gitdir); strbuf_release(&dotgit); + free(path); } void repair_worktrees_after_gitdir_move(const char *old_path) @@ -731,8 +773,7 @@ static ssize_t infer_backlink(const char *gitfile, struct strbuf *inferred) id++; /* advance past '/' to point at <id> */ if (!*id) goto error; - strbuf_reset(inferred); - strbuf_git_common_path(inferred, the_repository, "worktrees/%s", id); + repo_common_path_replace(the_repository, inferred, "worktrees/%s", id); if (!is_directory(inferred->buf)) goto error; @@ -870,7 +911,11 @@ int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath, ssize_t read_result; *wtpath = NULL; - strbuf_realpath(&repo, git_common_path("worktrees/%s", id), 1); + + path = repo_common_path(the_repository, "worktrees/%s", id); + strbuf_realpath(&repo, path, 1); + FREE_AND_NULL(path); + strbuf_addf(&gitdir, "%s/gitdir", repo.buf); if (!is_directory(repo.buf)) { strbuf_addstr(reason, _("not a valid directory")); diff --git a/worktree.h b/worktree.h index 38145df80f..e4bcccdc0a 100644 --- a/worktree.h +++ b/worktree.h @@ -31,6 +31,14 @@ struct worktree { struct worktree **get_worktrees(void); /* + * Like `get_worktrees`, but does not read HEAD. Skip reading HEAD allows to + * get the worktree without worrying about failures pertaining to parsing + * the HEAD ref. This is useful in contexts where it is assumed that the + * refdb may not be in a consistent state. + */ +struct worktree **get_worktrees_without_reading_head(void); + +/* * Returns 1 if linked worktrees exist, 0 otherwise. */ int submodule_uses_worktrees(const char *path); @@ -39,7 +47,7 @@ int submodule_uses_worktrees(const char *path); * Return git dir of the worktree. Note that the path may be relative. * If wt is NULL, git dir of current worktree is returned. */ -const char *get_worktree_git_dir(const struct worktree *wt); +char *get_worktree_git_dir(const struct worktree *wt); /* * Search for the worktree identified unambiguously by `arg` -- typically @@ -479,7 +479,7 @@ int git_mkstemps_mode(char *pattern, int suffix_len, int mode) for (count = 0; count < TMP_MAX; ++count) { int i; uint64_t v; - if (csprng_bytes(&v, sizeof(v)) < 0) + if (csprng_bytes(&v, sizeof(v), 0) < 0) return error_errno("unable to get random bytes for temporary file"); /* Fill in the random bits. */ @@ -750,7 +750,7 @@ int open_nofollow(const char *path, int flags) #endif } -int csprng_bytes(void *buf, size_t len) +int csprng_bytes(void *buf, size_t len, MAYBE_UNUSED unsigned flags) { #if defined(HAVE_ARC4RANDOM) || defined(HAVE_ARC4RANDOM_LIBBSD) /* This function never returns an error. */ @@ -785,14 +785,18 @@ int csprng_bytes(void *buf, size_t len) return -1; return 0; #elif defined(HAVE_OPENSSL_CSPRNG) - int res = RAND_bytes(buf, len); - if (res == 1) + switch (RAND_pseudo_bytes(buf, len)) { + case 1: return 0; - if (res == -1) - errno = ENOTSUP; - else + case 0: + if (flags & CSPRNG_BYTES_INSECURE) + return 0; errno = EIO; - return -1; + return -1; + default: + errno = ENOTSUP; + return -1; + } #else ssize_t res; char *p = buf; @@ -816,11 +820,11 @@ int csprng_bytes(void *buf, size_t len) #endif } -uint32_t git_rand(void) +uint32_t git_rand(unsigned flags) { uint32_t result; - if (csprng_bytes(&result, sizeof(result)) < 0) + if (csprng_bytes(&result, sizeof(result), flags) < 0) die(_("unable to get random bytes")); return result; @@ -127,18 +127,26 @@ int open_nofollow(const char *path, int flags); void sleep_millisec(int millisec); +enum { + /* + * Accept insecure bytes, which some CSPRNG implementations may return + * in case the entropy pool has been exhausted. + */ + CSPRNG_BYTES_INSECURE = (1 << 0), +}; + /* * Generate len bytes from the system cryptographically secure PRNG. * Returns 0 on success and -1 on error, setting errno. The inability to - * satisfy the full request is an error. + * satisfy the full request is an error. Accepts CSPRNG flags. */ -int csprng_bytes(void *buf, size_t len); +int csprng_bytes(void *buf, size_t len, unsigned flags); /* * Returns a random uint32_t, uniformly distributed across all possible - * values. + * values. Accepts CSPRNG flags. */ -uint32_t git_rand(void); +uint32_t git_rand(unsigned flags); /* Provide log2 of the given `size_t`. */ static inline unsigned log2u(uintmax_t sz) diff --git a/wt-status.c b/wt-status.c index 3ee9181764..1da5732f57 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1289,7 +1289,8 @@ static void show_am_in_progress(struct wt_status *s, static char *read_line_from_git_path(const char *filename) { struct strbuf buf = STRBUF_INIT; - FILE *fp = fopen_or_warn(git_path("%s", filename), "r"); + FILE *fp = fopen_or_warn(repo_git_path_append(the_repository, &buf, + "%s", filename), "r"); if (!fp) { strbuf_release(&buf); @@ -1383,27 +1384,33 @@ static void abbrev_oid_in_line(struct strbuf *line) static int read_rebase_todolist(const char *fname, struct string_list *lines) { - struct strbuf line = STRBUF_INIT; - FILE *f = fopen(git_path("%s", fname), "r"); + struct strbuf buf = STRBUF_INIT; + FILE *f = fopen(repo_git_path_append(the_repository, &buf, "%s", fname), "r"); + int ret; if (!f) { - if (errno == ENOENT) - return -1; + if (errno == ENOENT) { + ret = -1; + goto out; + } die_errno("Could not open file %s for reading", - git_path("%s", fname)); + repo_git_path_replace(the_repository, &buf, "%s", fname)); } - while (!strbuf_getline_lf(&line, f)) { - if (starts_with(line.buf, comment_line_str)) + while (!strbuf_getline_lf(&buf, f)) { + if (starts_with(buf.buf, comment_line_str)) continue; - strbuf_trim(&line); - if (!line.len) + strbuf_trim(&buf); + if (!buf.len) continue; - abbrev_oid_in_line(&line); - string_list_append(lines, line.buf); + abbrev_oid_in_line(&buf); + string_list_append(lines, buf.buf); } fclose(f); - strbuf_release(&line); - return 0; + + ret = 0; +out: + strbuf_release(&buf); + return ret; } static void show_rebase_information(struct wt_status *s, @@ -1434,9 +1441,12 @@ static void show_rebase_information(struct wt_status *s, i < have_done.nr; i++) status_printf_ln(s, color, " %s", have_done.items[i].string); - if (have_done.nr > nr_lines_to_show && s->hints) + if (have_done.nr > nr_lines_to_show && s->hints) { + char *path = repo_git_path(the_repository, "rebase-merge/done"); status_printf_ln(s, color, - _(" (see more in file %s)"), git_path("rebase-merge/done")); + _(" (see more in file %s)"), path); + free(path); + } } if (yet_to_do.nr == 0) diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h index bb56b23f34..2cecde5afe 100644 --- a/xdiff/xdiff.h +++ b/xdiff/xdiff.h @@ -85,7 +85,7 @@ typedef struct s_xpparam { regex_t **ignore_regex; size_t ignore_regex_nr; - /* See Documentation/diff-options.txt. */ + /* See Documentation/diff-options.adoc. */ char **anchors; size_t anchors_nr; } xpparam_t; diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c index 4685ba6137..8889b8b62a 100644 --- a/xdiff/xdiffi.c +++ b/xdiff/xdiffi.c @@ -19,7 +19,6 @@ * Davide Libenzi <davidel@xmailserver.org> * */ -#define DISABLE_SIGN_COMPARE_WARNINGS #include "xinclude.h" @@ -1014,7 +1013,7 @@ static void xdl_mark_ignorable_lines(xdchange_t *xscr, xdfenv_t *xe, long flags) static int record_matches_regex(xrecord_t *rec, xpparam_t const *xpp) { regmatch_t regmatch; - int i; + size_t i; for (i = 0; i < xpp->ignore_regex_nr; i++) if (!regexec_buf(xpp->ignore_regex[i], rec->ptr, rec->size, 1, diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 75f0fe4986..f8e3f25b03 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -54,7 +54,7 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg) xdchange_t *xch, *xchp, *lxch; long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen; long max_ignorable = xecfg->ctxlen; - unsigned long ignored = 0; /* number of ignored blank lines */ + long ignored = 0; /* number of ignored blank lines */ /* remove ignorable changes that are too far before other changes */ for (xchp = *xscr; xchp && xchp->ignore; xchp = xchp->next) { diff --git a/xdiff/xhistogram.c b/xdiff/xhistogram.c index 16a8fe2f3f..040d81e0bc 100644 --- a/xdiff/xhistogram.c +++ b/xdiff/xhistogram.c @@ -106,7 +106,7 @@ static int scanA(struct histindex *index, int line1, int count1) unsigned int chain_len; struct record **rec_chain, *rec; - for (ptr = LINE_END(1); line1 <= ptr; ptr--) { + for (ptr = LINE_END(1); (unsigned int)line1 <= ptr; ptr--) { tbl_idx = TABLE_HASH(index, 1, ptr); rec_chain = index->records + tbl_idx; rec = *rec_chain; @@ -181,14 +181,14 @@ static int try_lcs(struct histindex *index, struct region *lcs, int b_ptr, be = bs; rc = rec->cnt; - while (line1 < as && line2 < bs + while ((unsigned int)line1 < as && (unsigned int)line2 < bs && CMP(index, 1, as - 1, 2, bs - 1)) { as--; bs--; if (1 < rc) rc = XDL_MIN(rc, CNT(index, as)); } - while (ae < LINE_END(1) && be < LINE_END(2) + while (ae < (unsigned int)LINE_END(1) && be < (unsigned int)LINE_END(2) && CMP(index, 1, ae + 1, 2, be + 1)) { ae++; be++; @@ -313,7 +313,7 @@ redo: if (count1 <= 0 && count2 <= 0) return 0; - if (LINE_END(1) >= MAX_PTR) + if ((unsigned int)LINE_END(1) >= MAX_PTR) return -1; if (!count1) { diff --git a/xdiff/xinclude.h b/xdiff/xinclude.h index 7e56542526..a4285ac0eb 100644 --- a/xdiff/xinclude.h +++ b/xdiff/xinclude.h @@ -23,8 +23,6 @@ #if !defined(XINCLUDE_H) #define XINCLUDE_H -#define DISABLE_SIGN_COMPARE_WARNINGS - #include "git-compat-util.h" #include "xmacros.h" #include "xdiff.h" diff --git a/xdiff/xpatience.c b/xdiff/xpatience.c index a2d8955537..77dc411d19 100644 --- a/xdiff/xpatience.c +++ b/xdiff/xpatience.c @@ -19,6 +19,7 @@ * Davide Libenzi <davidel@xmailserver.org> * */ + #include "xinclude.h" /* @@ -63,7 +64,7 @@ struct hashmap { /* * If 1, this entry can serve as an anchor. See - * Documentation/diff-options.txt for more information. + * Documentation/diff-options.adoc for more information. */ unsigned anchor : 1; } *entries, *first, *last; @@ -75,7 +76,7 @@ struct hashmap { static int is_anchor(xpparam_t const *xpp, const char *line) { - int i; + size_t i; for (i = 0; i < xpp->anchors_nr; i++) { if (!strncmp(line, xpp->anchors[i], strlen(xpp->anchors[i]))) return 1; diff --git a/xdiff/xutils.c b/xdiff/xutils.c index 9e36f24875..444a108f87 100644 --- a/xdiff/xutils.c +++ b/xdiff/xutils.c @@ -375,7 +375,7 @@ static int xdl_format_hunk_hdr(long s1, long c1, long s2, long c2, nb += 3; if (func && funclen) { buf[nb++] = ' '; - if (funclen > sizeof(buf) - nb - 1) + if ((size_t)funclen > sizeof(buf) - nb - 1) funclen = sizeof(buf) - nb - 1; memcpy(buf + nb, func, funclen); nb += funclen; @@ -437,7 +437,7 @@ void* xdl_alloc_grow_helper(void *p, long nr, long *alloc, size_t size) { void *tmp = NULL; size_t n = ((LONG_MAX - 16) / 2 >= *alloc) ? 2 * *alloc + 16 : LONG_MAX; - if (nr > n) + if ((size_t)nr > n) n = nr; if (SIZE_MAX / size >= n) tmp = xdl_realloc(p, n * size); |
