From 5e402e54e7f0d9eaa85987ced8913f2709f2be5c Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Tue, 12 May 2009 22:20:23 +0200 Subject: [PATCH 001/211] gitk: Update German translation. Signed-off-by: Christian Stimming Signed-off-by: Paul Mackerras --- po/de.po | 680 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 373 insertions(+), 307 deletions(-) diff --git a/po/de.po b/po/de.po index 825dc98f74..53ef0d6359 100644 --- a/po/de.po +++ b/po/de.po @@ -1,14 +1,15 @@ # Translation of gitk to German. # Copyright (C) 2007 Paul Mackerras. # This file is distributed under the same license as the gitk package. -# Christian Stimming , 2007 # +# Christian Stimming , 2007. +# Frederik Schwarzer , 2008. msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-12-06 20:40+0100\n" -"PO-Revision-Date: 2008-12-06 20:45+0100\n" +"POT-Creation-Date: 2009-05-12 21:55+0200\n" +"PO-Revision-Date: 2009-05-12 22:18+0200\n" "Last-Translator: Christian Stimming \n" "Language-Team: German\n" "MIME-Version: 1.0\n" @@ -17,297 +18,314 @@ msgstr "" #: gitk:113 msgid "Couldn't get list of unmerged files:" -msgstr "Liste der nicht-zusammengeführten Dateien nicht gefunden:" +msgstr "Liste der nicht zusammengeführten Dateien nicht gefunden:" -#: gitk:272 +#: gitk:268 msgid "Error parsing revisions:" msgstr "Fehler beim Laden der Versionen:" -#: gitk:327 +#: gitk:323 msgid "Error executing --argscmd command:" -msgstr "Fehler beim --argscmd Kommando:" +msgstr "Fehler beim Ausführen des --argscmd-Kommandos:" -#: gitk:340 +#: gitk:336 msgid "No files selected: --merge specified but no files are unmerged." msgstr "" -"Keine Dateien ausgewählt: --merge angegeben, es existieren aber keine nicht-" -"zusammengeführten Dateien." +"Keine Dateien ausgewählt: Es wurde --merge angegeben, aber es existieren " +"keine nicht zusammengeführten Dateien." -#: gitk:343 +#: gitk:339 msgid "" "No files selected: --merge specified but no unmerged files are within file " "limit." msgstr "" -"Keine Dateien ausgewähle: --merge angegeben, aber keine nicht-" -"zusammengeführten Dateien sind in der Dateiauswahl." +"Keine Dateien ausgewählt: Es wurde --merge angegeben, aber es sind keine " +"nicht zusammengeführten Dateien in der Dateiauswahl." -#: gitk:365 gitk:503 +#: gitk:361 gitk:508 msgid "Error executing git log:" -msgstr "Fehler beim Ausführen von git-log:" +msgstr "Fehler beim Ausführen von »git log«:" -#: gitk:378 +#: gitk:379 gitk:524 msgid "Reading" msgstr "Lesen" -#: gitk:438 gitk:3462 +#: gitk:439 gitk:4061 msgid "Reading commits..." -msgstr "Versionen lesen..." +msgstr "Versionen werden gelesen ..." -#: gitk:441 gitk:1528 gitk:3465 +#: gitk:442 gitk:1560 gitk:4064 msgid "No commits selected" -msgstr "Keine Versionen ausgewählt." +msgstr "Keine Versionen ausgewählt" -#: gitk:1399 +#: gitk:1436 msgid "Can't parse git log output:" -msgstr "Ausgabe von git-log kann nicht erkannt werden:" +msgstr "Ausgabe von »git log« kann nicht erkannt werden:" -#: gitk:1605 +#: gitk:1656 msgid "No commit information available" msgstr "Keine Versionsinformation verfügbar" -#: gitk:1709 gitk:1731 gitk:3259 gitk:7764 gitk:9293 gitk:9466 +#: gitk:1791 gitk:1815 gitk:3854 gitk:8714 gitk:10250 gitk:10422 msgid "OK" msgstr "Ok" -#: gitk:1733 gitk:3260 gitk:7439 gitk:7510 gitk:7613 gitk:7660 gitk:7766 -#: gitk:9294 gitk:9467 +#: gitk:1817 gitk:3856 gitk:8311 gitk:8385 gitk:8495 gitk:8544 gitk:8716 +#: gitk:10251 gitk:10423 msgid "Cancel" msgstr "Abbrechen" -#: gitk:1811 +#: gitk:1917 msgid "Update" msgstr "Aktualisieren" -#: gitk:1812 +#: gitk:1918 msgid "Reload" msgstr "Neu laden" -#: gitk:1813 +#: gitk:1919 msgid "Reread references" msgstr "Zweige neu laden" -#: gitk:1814 +#: gitk:1920 msgid "List references" msgstr "Zweige/Markierungen auflisten" -#: gitk:1915 +#: gitk:1922 msgid "Start git gui" msgstr "»git gui« starten" -#: gitk:1917 +#: gitk:1924 msgid "Quit" msgstr "Beenden" -#: gitk:1810 +#: gitk:1916 msgid "File" msgstr "Datei" -#: gitk:1818 +#: gitk:1928 msgid "Preferences" msgstr "Einstellungen" -#: gitk:1817 +#: gitk:1927 msgid "Edit" msgstr "Bearbeiten" -#: gitk:1821 +#: gitk:1932 msgid "New view..." -msgstr "Neue Ansicht..." +msgstr "Neue Ansicht ..." -#: gitk:1822 +#: gitk:1933 msgid "Edit view..." -msgstr "Ansicht bearbeiten..." +msgstr "Ansicht bearbeiten ..." -#: gitk:1823 +#: gitk:1934 msgid "Delete view" -msgstr "Ansicht löschen" +msgstr "Ansicht entfernen" -#: gitk:1825 +#: gitk:1936 msgid "All files" msgstr "Alle Dateien" -#: gitk:1820 gitk:3196 +#: gitk:1931 gitk:3666 msgid "View" msgstr "Ansicht" -#: gitk:1828 gitk:2487 +#: gitk:1941 gitk:1951 gitk:2650 msgid "About gitk" msgstr "Über gitk" -#: gitk:1829 +#: gitk:1942 gitk:1956 msgid "Key bindings" msgstr "Tastenkürzel" -#: gitk:1827 +#: gitk:1940 gitk:1955 msgid "Help" msgstr "Hilfe" -#: gitk:1887 +#: gitk:2016 msgid "SHA1 ID: " msgstr "SHA1:" -#: gitk:1918 +#: gitk:2047 msgid "Row" msgstr "Zeile" -#: gitk:1949 +#: gitk:2078 msgid "Find" msgstr "Suche" -#: gitk:1950 +#: gitk:2079 msgid "next" msgstr "nächste" -#: gitk:1951 +#: gitk:2080 msgid "prev" msgstr "vorige" -#: gitk:1952 +#: gitk:2081 msgid "commit" msgstr "Version nach" -#: gitk:1955 gitk:1957 gitk:3617 gitk:3640 gitk:3664 gitk:5550 gitk:5621 +#: gitk:2084 gitk:2086 gitk:4222 gitk:4245 gitk:4269 gitk:6210 gitk:6282 +#: gitk:6366 msgid "containing:" msgstr "Beschreibung:" -#: gitk:1958 gitk:2954 gitk:2959 gitk:3692 +#: gitk:2087 gitk:3158 gitk:3163 gitk:4297 msgid "touching paths:" msgstr "Dateien:" -#: gitk:1959 gitk:3697 +#: gitk:2088 gitk:4302 msgid "adding/removing string:" msgstr "Änderungen:" -#: gitk:1968 gitk:1970 +#: gitk:2097 gitk:2099 msgid "Exact" msgstr "Exakt" -#: gitk:1970 gitk:3773 gitk:5518 +#: gitk:2099 gitk:4377 gitk:6178 msgid "IgnCase" msgstr "Kein Groß/Klein" -#: gitk:1970 gitk:3666 gitk:3771 gitk:5514 +#: gitk:2099 gitk:4271 gitk:4375 gitk:6174 msgid "Regexp" msgstr "Regexp" -#: gitk:1972 gitk:1973 gitk:3792 gitk:3822 gitk:3829 gitk:5641 gitk:5708 +#: gitk:2101 gitk:2102 gitk:4396 gitk:4426 gitk:4433 gitk:6302 gitk:6370 msgid "All fields" msgstr "Alle Felder" -#: gitk:1973 gitk:3790 gitk:3822 gitk:5580 +#: gitk:2102 gitk:4394 gitk:4426 gitk:6241 msgid "Headline" msgstr "Überschrift" -#: gitk:1974 gitk:3790 gitk:5580 gitk:5708 gitk:6109 +#: gitk:2103 gitk:4394 gitk:6241 gitk:6370 gitk:6804 msgid "Comments" msgstr "Beschreibung" -#: gitk:1974 gitk:3790 gitk:3794 gitk:3829 gitk:5580 gitk:6045 gitk:7285 -#: gitk:7300 +#: gitk:2103 gitk:4394 gitk:4398 gitk:4433 gitk:6241 gitk:6739 gitk:7991 +#: gitk:8006 msgid "Author" msgstr "Autor" -#: gitk:1974 gitk:3790 gitk:5580 gitk:6047 +#: gitk:2103 gitk:4394 gitk:6241 gitk:6741 msgid "Committer" msgstr "Eintragender" -#: gitk:2003 +#: gitk:2132 msgid "Search" -msgstr "Suche" +msgstr "Suchen" -#: gitk:2010 +#: gitk:2139 msgid "Diff" msgstr "Vergleich" -#: gitk:2012 +#: gitk:2141 msgid "Old version" msgstr "Alte Version" -#: gitk:2014 +#: gitk:2143 msgid "New version" msgstr "Neue Version" -#: gitk:2016 +#: gitk:2145 msgid "Lines of context" msgstr "Kontextzeilen" -#: gitk:2026 +#: gitk:2155 msgid "Ignore space change" msgstr "Leerzeichenänderungen ignorieren" -#: gitk:2084 +#: gitk:2213 msgid "Patch" msgstr "Patch" -#: gitk:2086 +#: gitk:2215 msgid "Tree" msgstr "Baum" -#: gitk:2213 gitk:2226 +#: gitk:2359 gitk:2376 msgid "Diff this -> selected" -msgstr "Vergleich diese -> gewählte" +msgstr "Vergleich: diese -> gewählte" -#: gitk:2214 gitk:2227 +#: gitk:2360 gitk:2377 msgid "Diff selected -> this" -msgstr "Vergleich gewählte -> diese" +msgstr "Vergleich: gewählte -> diese" -#: gitk:2215 gitk:2228 +#: gitk:2361 gitk:2378 msgid "Make patch" msgstr "Patch erstellen" -#: gitk:2216 gitk:7494 +#: gitk:2362 gitk:8369 msgid "Create tag" msgstr "Markierung erstellen" -#: gitk:2217 gitk:7593 +#: gitk:2363 gitk:8475 msgid "Write commit to file" msgstr "Version in Datei schreiben" -#: gitk:2218 gitk:7647 +#: gitk:2364 gitk:8532 msgid "Create new branch" msgstr "Neuen Zweig erstellen" -#: gitk:2219 +#: gitk:2365 msgid "Cherry-pick this commit" msgstr "Diese Version pflücken" -#: gitk:2220 +#: gitk:2366 msgid "Reset HEAD branch to here" msgstr "HEAD-Zweig auf diese Version zurücksetzen" -#: gitk:2234 +#: gitk:2367 +msgid "Mark this commit" +msgstr "Lesezeichen setzen" + +#: gitk:2368 +msgid "Return to mark" +msgstr "Zum Lesezeichen" + +#: gitk:2369 +msgid "Find descendant of this and mark" +msgstr "Abkömmling von Lesezeichen und dieser Version finden" + +#: gitk:2370 +msgid "Compare with marked commit" +msgstr "Mit Lesezeichen vergleichen" + +#: gitk:2384 msgid "Check out this branch" msgstr "Auf diesen Zweig umstellen" -#: gitk:2235 +#: gitk:2385 msgid "Remove this branch" msgstr "Zweig löschen" -#: gitk:2242 +#: gitk:2392 msgid "Highlight this too" msgstr "Diesen auch hervorheben" -#: gitk:2243 +#: gitk:2393 msgid "Highlight this only" msgstr "Nur diesen hervorheben" -#: gitk:2244 +#: gitk:2394 msgid "External diff" -msgstr "Externer Vergleich" +msgstr "Externes Diff-Programm" -#: gitk:2255 +#: gitk:2395 msgid "Blame parent commit" msgstr "Annotieren der Elternversion" -#: gitk:2360 +#: gitk:2402 msgid "Show origin of this line" msgstr "Herkunft dieser Zeile anzeigen" -#: gitk:2361 +#: gitk:2403 msgid "Run git gui blame on this line" -msgstr "Annotieren (»git gui blame«) von dieser Zeile" +msgstr "Diese Zeile annotieren (»git gui blame«)" -#: gitk:2606 +#: gitk:2652 msgid "" "\n" "Gitk - a commit viewer for git\n" @@ -317,504 +335,552 @@ msgid "" "Use and redistribute under the terms of the GNU General Public License" msgstr "" "\n" -"Gitk - eine Visualisierung der Git Historie\n" +"Gitk - eine Visualisierung der Git-Historie\n" "\n" "Copyright © 2005-2008 Paul Mackerras\n" "\n" "Benutzung und Weiterverbreitung gemäß den Bedingungen der GNU General Public " "License" -#: gitk:2496 gitk:2557 gitk:7943 +#: gitk:2660 gitk:2722 gitk:8897 msgid "Close" msgstr "Schließen" -#: gitk:2515 +#: gitk:2679 msgid "Gitk key bindings" -msgstr "Gitk Tastaturbelegung" +msgstr "Gitk-Tastaturbelegung" -#: gitk:2517 +#: gitk:2682 msgid "Gitk key bindings:" -msgstr "Gitk Tastaturbelegung:" +msgstr "Gitk-Tastaturbelegung:" -#: gitk:2519 +#: gitk:2684 #, tcl-format msgid "<%s-Q>\t\tQuit" msgstr "<%s-Q>\t\tBeenden" -#: gitk:2520 +#: gitk:2685 msgid "\t\tMove to first commit" msgstr "\t\tZur neuesten Version springen" -#: gitk:2521 +#: gitk:2686 msgid "\t\tMove to last commit" msgstr "\t\tZur ältesten Version springen" -#: gitk:2522 +#: gitk:2687 msgid ", p, i\tMove up one commit" msgstr ", p, i\tNächste neuere Version" -#: gitk:2523 +#: gitk:2688 msgid ", n, k\tMove down one commit" msgstr ", n, k\tNächste ältere Version" -#: gitk:2524 +#: gitk:2689 msgid ", z, j\tGo back in history list" msgstr ", z, j\tEine Version zurückgehen" -#: gitk:2525 +#: gitk:2690 msgid ", x, l\tGo forward in history list" msgstr ", x, l\tEine Version weitergehen" -#: gitk:2526 +#: gitk:2691 msgid "\tMove up one page in commit list" msgstr "\tEine Seite nach oben blättern" -#: gitk:2527 +#: gitk:2692 msgid "\tMove down one page in commit list" msgstr "\tEine Seite nach unten blättern" -#: gitk:2528 +#: gitk:2693 #, tcl-format msgid "<%s-Home>\tScroll to top of commit list" msgstr "<%s-Pos1>\tZum oberen Ende der Versionsliste blättern" -#: gitk:2529 +#: gitk:2694 #, tcl-format msgid "<%s-End>\tScroll to bottom of commit list" msgstr "<%s-Ende>\tZum unteren Ende der Versionsliste blättern" -#: gitk:2530 +#: gitk:2695 #, tcl-format msgid "<%s-Up>\tScroll commit list up one line" msgstr "<%s-Hoch>\tVersionsliste eine Zeile nach oben blättern" -#: gitk:2531 +#: gitk:2696 #, tcl-format msgid "<%s-Down>\tScroll commit list down one line" msgstr "<%s-Runter>\tVersionsliste eine Zeile nach unten blättern" -#: gitk:2532 +#: gitk:2697 #, tcl-format msgid "<%s-PageUp>\tScroll commit list up one page" -msgstr "<%s-BildHoch>\tVersionsliste eine Seite hoch blättern" +msgstr "<%s-BildHoch>\tVersionsliste eine Seite nach oben blättern" -#: gitk:2533 +#: gitk:2698 #, tcl-format msgid "<%s-PageDown>\tScroll commit list down one page" msgstr "<%s-BildRunter>\tVersionsliste eine Seite nach unten blättern" -#: gitk:2534 +#: gitk:2699 msgid "\tFind backwards (upwards, later commits)" msgstr "\tRückwärts suchen (nach oben; neuere Versionen)" -#: gitk:2535 +#: gitk:2700 msgid "\tFind forwards (downwards, earlier commits)" msgstr " Suchen (nach unten; ältere Versionen)" -#: gitk:2536 +#: gitk:2701 msgid ", b\tScroll diff view up one page" msgstr ", b\t\tVergleich eine Seite nach oben blättern" -#: gitk:2537 +#: gitk:2702 msgid "\tScroll diff view up one page" msgstr "\tVergleich eine Seite nach oben blättern" -#: gitk:2538 +#: gitk:2703 msgid "\t\tScroll diff view down one page" msgstr "\tVergleich eine Seite nach unten blättern" -#: gitk:2539 +#: gitk:2704 msgid "u\t\tScroll diff view up 18 lines" -msgstr "u\t\tVergleich um 18 Zeilen nach oben (»up«) blättern" +msgstr "u\t\tVergleich um 18 Zeilen nach oben blättern" -#: gitk:2540 +#: gitk:2705 msgid "d\t\tScroll diff view down 18 lines" -msgstr "d\t\tVergleich um 18 Zeilen nach unten (»down«) blättern" +msgstr "d\t\tVergleich um 18 Zeilen nach unten blättern" -#: gitk:2541 +#: gitk:2706 #, tcl-format msgid "<%s-F>\t\tFind" msgstr "<%s-F>\t\tSuchen" -#: gitk:2542 +#: gitk:2707 #, tcl-format msgid "<%s-G>\t\tMove to next find hit" msgstr "<%s-G>\t\tWeitersuchen" -#: gitk:2543 +#: gitk:2708 msgid "\tMove to next find hit" msgstr "\tWeitersuchen" -#: gitk:2544 -msgid "/\t\tMove to next find hit, or redo find" -msgstr "/\t\tWeitersuchen oder neue Suche beginnen" +#: gitk:2709 +msgid "/\t\tFocus the search box" +msgstr "/\t\tTastaturfokus ins Suchfeld" -#: gitk:2545 +#: gitk:2710 msgid "?\t\tMove to previous find hit" msgstr "?\t\tRückwärts weitersuchen" -#: gitk:2546 +#: gitk:2711 msgid "f\t\tScroll diff view to next file" -msgstr "f\t\tVergleich zur nächsten Datei (»file«) blättern" +msgstr "f\t\tVergleich zur nächsten Datei blättern" -#: gitk:2547 +#: gitk:2712 #, tcl-format msgid "<%s-S>\t\tSearch for next hit in diff view" msgstr "<%s-S>\t\tWeitersuchen im Vergleich" -#: gitk:2548 +#: gitk:2713 #, tcl-format msgid "<%s-R>\t\tSearch for previous hit in diff view" msgstr "<%s-R>\t\tRückwärts weitersuchen im Vergleich" -#: gitk:2549 +#: gitk:2714 #, tcl-format msgid "<%s-KP+>\tIncrease font size" -msgstr "<%s-Nummerblock-Plus>\tSchriftgröße vergrößern" +msgstr "<%s-Nummerblock-Plus>\tSchrift vergrößern" -#: gitk:2550 +#: gitk:2715 #, tcl-format msgid "<%s-plus>\tIncrease font size" -msgstr "<%s-Plus>\tSchriftgröße vergrößern" +msgstr "<%s-Plus>\tSchrift vergrößern" -#: gitk:2551 +#: gitk:2716 #, tcl-format msgid "<%s-KP->\tDecrease font size" -msgstr "<%s-Nummernblock-> Schriftgröße verkleinern" +msgstr "<%s-Nummernblock-Minus> Schrift verkleinern" -#: gitk:2552 +#: gitk:2717 #, tcl-format msgid "<%s-minus>\tDecrease font size" -msgstr "<%s-Minus>\tSchriftgröße verkleinern" +msgstr "<%s-Minus>\tSchrift verkleinern" -#: gitk:2553 +#: gitk:2718 msgid "\t\tUpdate" msgstr "\t\tAktualisieren" -#: gitk:2979 +#: gitk:3173 #, tcl-format msgid "Error getting \"%s\" from %s:" msgstr "Fehler beim Holen von »%s« von »%s«:" -#: gitk:3036 gitk:3045 +#: gitk:3230 gitk:3239 #, tcl-format msgid "Error creating temporary directory %s:" -msgstr "Fehler beim Erzeugen eines temporären Verzeichnisses »%s«:" +msgstr "Fehler beim Erzeugen des temporären Verzeichnisses »%s«:" -#: gitk:3058 +#: gitk:3251 msgid "command failed:" msgstr "Kommando fehlgeschlagen:" -#: gitk:3078 +#: gitk:3397 msgid "No such commit" msgstr "Version nicht gefunden" -#: gitk:3083 +#: gitk:3411 msgid "git gui blame: command failed:" msgstr "git gui blame: Kommando fehlgeschlagen:" -#: gitk:3398 +#: gitk:3442 #, tcl-format msgid "Couldn't read merge head: %s" msgstr "Zusammenführungs-Spitze konnte nicht gelesen werden: %s" -#: gitk:3406 +#: gitk:3450 #, tcl-format msgid "Error reading index: %s" msgstr "Fehler beim Lesen der Bereitstellung (»index«): %s" -#: gitk:3431 +#: gitk:3475 #, tcl-format msgid "Couldn't start git blame: %s" msgstr "»git blame« konnte nicht gestartet werden: %s" -#: gitk:3434 gitk:6160 +#: gitk:3478 gitk:6209 msgid "Searching" msgstr "Suchen" -#: gitk:3466 +#: gitk:3510 #, tcl-format msgid "Error running git blame: %s" msgstr "Fehler beim Ausführen von »git blame«: %s" -#: gitk:3494 +#: gitk:3538 #, tcl-format msgid "That line comes from commit %s, which is not in this view" msgstr "" -"Diese Zeile stammt aus Version %s, welche nicht in dieser Ansicht gezeigt " -"wird." +"Diese Zeile stammt aus Version %s, die nicht in dieser Ansicht gezeigt wird" -#: gitk:3508 +#: gitk:3552 msgid "External diff viewer failed:" -msgstr "Externes Vergleich-(Diff-)Programm fehlgeschlagen:" +msgstr "Externes Diff-Programm fehlgeschlagen:" -#: gitk:3210 +#: gitk:3670 msgid "Gitk view definition" -msgstr "Gitk Ansichten" +msgstr "Gitk-Ansichten" -#: gitk:3630 +#: gitk:3674 msgid "Remember this view" msgstr "Diese Ansicht speichern" -#: gitk:3232 +#: gitk:3675 msgid "Commits to include (arguments to git log):" -msgstr "Versionen anzeigen (Argumente von git-log):" +msgstr "Versionen anzeigen (Argumente von git log):" -#: gitk:3632 +#: gitk:3676 msgid "Use all refs" msgstr "Alle Zweige verwenden" -#: gitk:3633 +#: gitk:3677 msgid "Strictly sort by date" msgstr "Streng nach Datum sortieren" -#: gitk:3634 +#: gitk:3678 msgid "Mark branch sides" msgstr "Zweig-Seiten markieren" -#: gitk:3635 +#: gitk:3679 msgid "Since date:" msgstr "Von Datum:" -#: gitk:3636 +#: gitk:3680 msgid "Until date:" msgstr "Bis Datum:" -#: gitk:3637 +#: gitk:3681 msgid "Max count:" msgstr "Max. Anzahl:" -#: gitk:3638 +#: gitk:3682 msgid "Skip:" msgstr "Überspringen:" -#: gitk:3639 +#: gitk:3683 msgid "Limit to first parent" msgstr "Auf erste Elternversion beschränken" -#: gitk:3640 +#: gitk:3684 msgid "Command to generate more commits to include:" msgstr "Versionsliste durch folgendes Kommando erzeugen lassen:" -#: gitk:3749 +#: gitk:3780 +msgid "Gitk: edit view" +msgstr "Gitk: Ansicht bearbeiten" + +#: gitk:3793 msgid "Name" msgstr "Name" -#: gitk:3797 +#: gitk:3841 msgid "Enter files and directories to include, one per line:" msgstr "Folgende Dateien und Verzeichnisse anzeigen (eine pro Zeile):" -#: gitk:3811 +#: gitk:3855 msgid "Apply (F5)" msgstr "Anwenden (F5)" -#: gitk:3849 +#: gitk:3893 msgid "Error in commit selection arguments:" msgstr "Fehler in den ausgewählten Versionen:" -#: gitk:3347 gitk:3399 gitk:3842 gitk:3856 gitk:5060 gitk:10141 gitk:10142 +#: gitk:3946 gitk:3998 gitk:4446 gitk:4460 gitk:5721 gitk:11114 gitk:11115 msgid "None" msgstr "Keine" -#: gitk:3790 gitk:5580 gitk:7287 gitk:7302 +#: gitk:4394 gitk:6241 gitk:7993 gitk:8008 msgid "Date" msgstr "Datum" -#: gitk:3790 gitk:5580 +#: gitk:4394 gitk:6241 msgid "CDate" msgstr "Eintragedatum" -#: gitk:3939 gitk:3944 +#: gitk:4543 gitk:4548 msgid "Descendant" msgstr "Abkömmling" -#: gitk:3940 +#: gitk:4544 msgid "Not descendant" -msgstr "Nicht Abkömmling" +msgstr "Kein Abkömmling" -#: gitk:3947 gitk:3952 +#: gitk:4551 gitk:4556 msgid "Ancestor" msgstr "Vorgänger" -#: gitk:3948 +#: gitk:4552 msgid "Not ancestor" -msgstr "Nicht Vorgänger" +msgstr "Kein Vorgänger" -#: gitk:4187 +#: gitk:4842 msgid "Local changes checked in to index but not committed" msgstr "Lokale Änderungen bereitgestellt, aber nicht eingetragen" -#: gitk:4220 +#: gitk:4878 msgid "Local uncommitted changes, not checked in to index" msgstr "Lokale Änderungen, nicht bereitgestellt" -#: gitk:6673 +#: gitk:6559 +msgid "many" +msgstr "viele" + +#: gitk:6743 msgid "Tags:" msgstr "Markierungen:" -#: gitk:6066 gitk:6072 gitk:7280 +#: gitk:6760 gitk:6766 gitk:7986 msgid "Parent" msgstr "Eltern" -#: gitk:6077 +#: gitk:6771 msgid "Child" msgstr "Kind" -#: gitk:6086 +#: gitk:6780 msgid "Branch" msgstr "Zweig" -#: gitk:6089 +#: gitk:6783 msgid "Follows" msgstr "Folgt auf" -#: gitk:6092 +#: gitk:6786 msgid "Precedes" msgstr "Vorgänger von" -#: gitk:7209 +#: gitk:7279 #, tcl-format msgid "Error getting diffs: %s" msgstr "Fehler beim Laden des Vergleichs: %s" -#: gitk:7748 +#: gitk:7819 msgid "Goto:" msgstr "Gehe zu:" -#: gitk:7115 +#: gitk:7821 msgid "SHA1 ID:" msgstr "SHA1-Hashwert:" -#: gitk:7134 +#: gitk:7840 #, tcl-format msgid "Short SHA1 id %s is ambiguous" msgstr "Kurzer SHA1-Hashwert »%s« ist mehrdeutig" -#: gitk:7146 +#: gitk:7852 #, tcl-format msgid "SHA1 id %s is not known" -msgstr "SHA1-Hashwert »%s« unbekannt" +msgstr "SHA1-Hashwert »%s« ist unbekannt" -#: gitk:7148 +#: gitk:7854 #, tcl-format msgid "Tag/Head %s is not known" msgstr "Markierung/Zweig »%s« ist unbekannt" -#: gitk:7290 +#: gitk:7996 msgid "Children" msgstr "Kinder" -#: gitk:7347 +#: gitk:8053 #, tcl-format msgid "Reset %s branch to here" msgstr "Zweig »%s« hierher zurücksetzen" -#: gitk:7349 +#: gitk:8055 msgid "Detached head: can't reset" msgstr "Zweigspitze ist abgetrennt: Zurücksetzen nicht möglich" -#: gitk:7381 +#: gitk:8164 gitk:8170 +msgid "Skipping merge commit " +msgstr "Überspringe Zusammenführungs-Version " + +#: gitk:8179 gitk:8184 +msgid "Error getting patch ID for " +msgstr "Fehler beim Holen der Patch-ID für " + +#: gitk:8180 gitk:8185 +msgid " - stopping\n" +msgstr " - Abbruch.\n" + +#: gitk:8190 gitk:8193 gitk:8201 gitk:8211 gitk:8220 +msgid "Commit " +msgstr "Version " + +#: gitk:8194 +msgid "" +" is the same patch as\n" +" " +msgstr "" +" ist das gleiche Patch wie\n" +" " + +#: gitk:8202 +msgid "" +" differs from\n" +" " +msgstr "" +" ist unterschiedlich von\n" +" " + +#: gitk:8204 +msgid "- stopping\n" +msgstr "- Abbruch.\n" + +#: gitk:8212 gitk:8221 +#, tcl-format +msgid " has %s children - stopping\n" +msgstr " hat %s Kinder. Abbruch\n" + +#: gitk:8252 msgid "Top" msgstr "Oben" -#: gitk:7382 +#: gitk:8253 msgid "From" msgstr "Von" -#: gitk:7387 +#: gitk:8258 msgid "To" msgstr "bis" -#: gitk:7410 +#: gitk:8282 msgid "Generate patch" msgstr "Patch erstellen" -#: gitk:7412 +#: gitk:8284 msgid "From:" msgstr "Von:" -#: gitk:7421 +#: gitk:8293 msgid "To:" msgstr "bis:" -#: gitk:7430 +#: gitk:8302 msgid "Reverse" msgstr "Umgekehrt" -#: gitk:7432 gitk:7607 +#: gitk:8304 gitk:8489 msgid "Output file:" msgstr "Ausgabedatei:" -#: gitk:7438 +#: gitk:8310 msgid "Generate" msgstr "Erzeugen" -#: gitk:7474 +#: gitk:8348 msgid "Error creating patch:" -msgstr "Fehler beim Patch erzeugen:" +msgstr "Fehler beim Erzeugen des Patches:" -#: gitk:7496 gitk:7595 gitk:7649 +#: gitk:8371 gitk:8477 gitk:8534 msgid "ID:" msgstr "ID:" -#: gitk:7505 +#: gitk:8380 msgid "Tag name:" msgstr "Markierungsname:" -#: gitk:7509 gitk:7659 +#: gitk:8384 gitk:8543 msgid "Create" msgstr "Erstellen" -#: gitk:7524 +#: gitk:8401 msgid "No tag name specified" msgstr "Kein Markierungsname angegeben" -#: gitk:7528 +#: gitk:8405 #, tcl-format msgid "Tag \"%s\" already exists" msgstr "Markierung »%s« existiert bereits." -#: gitk:7534 +#: gitk:8411 msgid "Error creating tag:" -msgstr "Fehler bei Markierung erstellen:" +msgstr "Fehler beim Erstellen der Markierung:" -#: gitk:7604 +#: gitk:8486 msgid "Command:" msgstr "Kommando:" -#: gitk:7612 +#: gitk:8494 msgid "Write" msgstr "Schreiben" -#: gitk:7628 +#: gitk:8512 msgid "Error writing commit:" msgstr "Fehler beim Schreiben der Version:" -#: gitk:7654 +#: gitk:8539 msgid "Name:" msgstr "Name:" -#: gitk:7674 +#: gitk:8562 msgid "Please specify a name for the new branch" msgstr "Bitte geben Sie einen Namen für den neuen Zweig an." -#: gitk:8328 +#: gitk:8567 #, tcl-format msgid "Branch '%s' already exists. Overwrite?" msgstr "Zweig »%s« existiert bereits. Soll er überschrieben werden?" -#: gitk:8394 +#: gitk:8633 #, tcl-format msgid "Commit %s is already included in branch %s -- really re-apply it?" msgstr "" "Version »%s« ist bereits im Zweig »%s« enthalten -- trotzdem erneut " "eintragen?" -#: gitk:7718 +#: gitk:8638 msgid "Cherry-picking" msgstr "Version pflücken" -#: gitk:8408 +#: gitk:8647 #, tcl-format msgid "" "Cherry-pick failed because of local changes to file '%s'.\n" @@ -822,45 +888,45 @@ msgid "" msgstr "" "Pflücken fehlgeschlagen, da noch lokale Änderungen in Datei »%s«\n" "vorliegen. Bitte diese Änderungen eintragen, zurücksetzen oder\n" -"zwischenspeichern (»git stash») und dann erneut versuchen." +"zwischenspeichern (»git stash«) und dann erneut versuchen." -#: gitk:8414 +#: gitk:8653 msgid "" "Cherry-pick failed because of merge conflict.\n" "Do you wish to run git citool to resolve it?" msgstr "" "Pflücken fehlgeschlagen, da ein Zusammenführungs-Konflikt aufgetreten\n" -"ist. Soll das »git citool« (Zusammenführungs-Werkzeug) aufgerufen\n" +"ist. Soll das Zusammenführungs-Werkzeug (»git citool«) aufgerufen\n" "werden, um diesen Konflikt aufzulösen?" -#: gitk:8430 +#: gitk:8669 msgid "No changes committed" msgstr "Keine Änderungen eingetragen" -#: gitk:7745 +#: gitk:8695 msgid "Confirm reset" msgstr "Zurücksetzen bestätigen" -#: gitk:7747 +#: gitk:8697 #, tcl-format msgid "Reset branch %s to %s?" msgstr "Zweig »%s« auf »%s« zurücksetzen?" -#: gitk:7751 +#: gitk:8701 msgid "Reset type:" msgstr "Art des Zurücksetzens:" -#: gitk:7755 +#: gitk:8705 msgid "Soft: Leave working tree and index untouched" msgstr "Harmlos: Arbeitskopie und Bereitstellung unverändert" -#: gitk:7758 +#: gitk:8708 msgid "Mixed: Leave working tree untouched, reset index" msgstr "" "Gemischt: Arbeitskopie unverändert,\n" "Bereitstellung zurückgesetzt" -#: gitk:7761 +#: gitk:8711 msgid "" "Hard: Reset working tree and index\n" "(discard ALL local changes)" @@ -868,21 +934,21 @@ msgstr "" "Hart: Arbeitskopie und Bereitstellung\n" "(Alle lokalen Änderungen werden gelöscht)" -#: gitk:7777 +#: gitk:8728 msgid "Resetting" msgstr "Zurücksetzen" -#: gitk:7834 +#: gitk:8785 msgid "Checking out" msgstr "Umstellen" -#: gitk:7885 +#: gitk:8838 msgid "Cannot delete the currently checked-out branch" msgstr "" "Der Zweig, auf den die Arbeitskopie momentan umgestellt ist, kann nicht " "gelöscht werden." -#: gitk:7891 +#: gitk:8844 #, tcl-format msgid "" "The commits on branch %s aren't on any other branch.\n" @@ -891,174 +957,174 @@ msgstr "" "Die Versionen auf Zweig »%s« existieren auf keinem anderen Zweig.\n" "Zweig »%s« trotzdem löschen?" -#: gitk:7922 +#: gitk:8875 #, tcl-format msgid "Tags and heads: %s" msgstr "Markierungen und Zweige: %s" -#: gitk:7936 +#: gitk:8890 msgid "Filter" msgstr "Filtern" -#: gitk:8230 +#: gitk:9185 msgid "" "Error reading commit topology information; branch and preceding/following " "tag information will be incomplete." msgstr "" -"Fehler beim Lesen der Strukturinformationen; Zweige und Vorgänger/Nachfolger " -"Informationen werden unvollständig sein." +"Fehler beim Lesen der Strukturinformationen; Zweige und Informationen zu " +"Vorgänger/Nachfolger werden unvollständig sein." -#: gitk:9216 +#: gitk:10171 msgid "Tag" msgstr "Markierung" -#: gitk:9216 +#: gitk:10171 msgid "Id" msgstr "Id" -#: gitk:9262 +#: gitk:10219 msgid "Gitk font chooser" -msgstr "Gitk Schriften wählen" +msgstr "Gitk-Schriften wählen" -#: gitk:9279 +#: gitk:10236 msgid "B" msgstr "F" -#: gitk:9282 +#: gitk:10239 msgid "I" msgstr "K" -#: gitk:9375 +#: gitk:10334 msgid "Gitk preferences" -msgstr "Gitk Einstellungen" +msgstr "Gitk-Einstellungen" -#: gitk:9376 +#: gitk:10336 msgid "Commit list display options" -msgstr "Anzeige Versionsliste" +msgstr "Anzeige der Versionsliste" -#: gitk:9379 +#: gitk:10339 msgid "Maximum graph width (lines)" msgstr "Maximale Graphenbreite (Zeilen)" -#: gitk:9383 +#: gitk:10343 #, tcl-format msgid "Maximum graph width (% of pane)" msgstr "Maximale Graphenbreite (% des Fensters)" -#: gitk:9388 +#: gitk:10347 msgid "Show local changes" msgstr "Lokale Änderungen anzeigen" -#: gitk:9393 +#: gitk:10350 msgid "Auto-select SHA1" -msgstr "SHA1-Hashwert automatisch markieren" +msgstr "SHA1-Hashwert automatisch auswählen" -#: gitk:9398 +#: gitk:10354 msgid "Diff display options" -msgstr "Anzeige Vergleich" +msgstr "Anzeige des Vergleichs" -#: gitk:9400 +#: gitk:10356 msgid "Tab spacing" msgstr "Tabulatorbreite" -#: gitk:9404 +#: gitk:10359 msgid "Display nearby tags" -msgstr "Naheliegende Überschriften anzeigen" +msgstr "Naheliegende Markierungen anzeigen" -#: gitk:9409 +#: gitk:10362 msgid "Limit diffs to listed paths" msgstr "Vergleich nur für angezeigte Pfade" -#: gitk:9414 +#: gitk:10365 msgid "Support per-file encodings" msgstr "Zeichenkodierung pro Datei ermitteln" -#: gitk:9421 +#: gitk:10371 gitk:10436 msgid "External diff tool" -msgstr "Externes Vergleich-(Diff-)Programm" +msgstr "Externes Diff-Programm" -#: gitk:9423 +#: gitk:10373 msgid "Choose..." -msgstr "Wählen..." +msgstr "Wählen ..." -#: gitk:9428 +#: gitk:10378 msgid "Colors: press to choose" msgstr "Farben: Klicken zum Wählen" -#: gitk:9431 +#: gitk:10381 msgid "Background" msgstr "Hintergrund" -#: gitk:10153 gitk:10183 +#: gitk:10382 gitk:10412 msgid "background" msgstr "Hintergrund" -#: gitk:10156 +#: gitk:10385 msgid "Foreground" msgstr "Vordergrund" -#: gitk:10157 +#: gitk:10386 msgid "foreground" msgstr "Vordergrund" -#: gitk:10160 +#: gitk:10389 msgid "Diff: old lines" msgstr "Vergleich: Alte Zeilen" -#: gitk:10161 +#: gitk:10390 msgid "diff old lines" msgstr "Vergleich - Alte Zeilen" -#: gitk:10165 +#: gitk:10394 msgid "Diff: new lines" msgstr "Vergleich: Neue Zeilen" -#: gitk:10166 +#: gitk:10395 msgid "diff new lines" msgstr "Vergleich - Neue Zeilen" -#: gitk:10170 +#: gitk:10399 msgid "Diff: hunk header" msgstr "Vergleich: Änderungstitel" -#: gitk:10172 +#: gitk:10401 msgid "diff hunk header" msgstr "Vergleich - Änderungstitel" -#: gitk:10176 +#: gitk:10405 msgid "Marked line bg" -msgstr "Markierte Zeile Hintergrund" +msgstr "Hintergrund für markierte Zeile" -#: gitk:10178 +#: gitk:10407 msgid "marked line background" -msgstr "markierte Zeile Hintergrund" +msgstr "Hintergrund für markierte Zeile" -#: gitk:10182 +#: gitk:10411 msgid "Select bg" -msgstr "Hintergrundfarbe Auswählen" +msgstr "Hintergrundfarbe auswählen" -#: gitk:9459 +#: gitk:10415 msgid "Fonts: press to choose" msgstr "Schriftart: Klicken zum Wählen" -#: gitk:9461 +#: gitk:10417 msgid "Main font" msgstr "Programmschriftart" -#: gitk:9462 +#: gitk:10418 msgid "Diff display font" -msgstr "Vergleich" +msgstr "Schriftart für Vergleich" -#: gitk:9463 +#: gitk:10419 msgid "User interface font" msgstr "Beschriftungen" -#: gitk:9488 +#: gitk:10446 #, tcl-format msgid "Gitk: choose color for %s" msgstr "Gitk: Farbe wählen für %s" -#: gitk:9934 +#: gitk:10893 msgid "" "Sorry, gitk cannot run with this version of Tcl/Tk.\n" " Gitk requires at least Tcl/Tk 8.4." @@ -1066,24 +1132,24 @@ msgstr "" "Gitk läuft nicht mit dieser Version von Tcl/Tk.\n" "Gitk benötigt mindestens Tcl/Tk 8.4." -#: gitk:10047 +#: gitk:11020 msgid "Cannot find a git repository here." msgstr "Kein Git-Projektarchiv gefunden." -#: gitk:10051 +#: gitk:11024 #, tcl-format msgid "Cannot find the git directory \"%s\"." msgstr "Git-Verzeichnis »%s« wurde nicht gefunden." -#: gitk:10098 +#: gitk:11071 #, tcl-format msgid "Ambiguous argument '%s': both revision and filename" msgstr "Mehrdeutige Angabe »%s«: Sowohl Version als auch Dateiname existiert." -#: gitk:10110 +#: gitk:11083 msgid "Bad arguments to gitk:" msgstr "Falsche Kommandozeilen-Parameter für gitk:" -#: gitk:10170 +#: gitk:11167 msgid "Command line" msgstr "Kommandozeile" From b5cda49040f77334dc08485e3f36ef8c8f2928b4 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Tue, 28 Apr 2009 14:03:54 +0200 Subject: [PATCH 002/211] gitk: Use --textconv to generate diff text For the most part gitk's focus is on showing history and changes in a human readable form. For this reason, it makes sense to generate the patch text in the diff view using --textconv so that textconv drivers are used if they are defined. gitk can also generate patches, but we do not use --textconv because such patches could not be applied. Signed-off-by: Johannes Sixt Signed-off-by: Paul Mackerras --- gitk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitk b/gitk index 1a7887b252..dcbfdc6538 100755 --- a/gitk +++ b/gitk @@ -7268,7 +7268,7 @@ proc getblobdiffs {ids} { global limitdiffs vfilelimit curview global diffencoding targetline diffnparents - set cmd [diffcmd $ids "-p -C --cc --no-commit-id -U$diffcontext"] + set cmd [diffcmd $ids "-p --textconv -C --cc --no-commit-id -U$diffcontext"] if {$ignorespace} { append cmd " -w" } From a8138733fcf4d9c175b53ab0d0f06a3f7c232286 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 16 May 2009 21:06:01 +1000 Subject: [PATCH 003/211] gitk: Check git version before using --textconv flag Commit 785b7535 ("gitk: use --textconv to generate diff text") added the --textconv flag to the git diff commands used to display commit diffs. Since some people use newer gitk with older git installations, this adds a check on the git version to check that it understands --textconv before using it. Signed-off-by: Paul Mackerras --- gitk | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gitk b/gitk index dcbfdc6538..5710782472 100755 --- a/gitk +++ b/gitk @@ -7267,8 +7267,13 @@ proc getblobdiffs {ids} { global ignorespace global limitdiffs vfilelimit curview global diffencoding targetline diffnparents + global git_version - set cmd [diffcmd $ids "-p --textconv -C --cc --no-commit-id -U$diffcontext"] + set textconv {} + if {[package vcompare $git_version "1.6.1"] >= 0} { + set textconv "--textconv" + } + set cmd [diffcmd $ids "-p $textconv -C --cc --no-commit-id -U$diffcontext"] if {$ignorespace} { append cmd " -w" } @@ -11090,6 +11095,7 @@ set nullid2 "0000000000000000000000000000000000000001" set nullfile "/dev/null" set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}] +set git_version [lindex [exec git version] end] set runq {} set history {} From 13d40b618a78ce236d103ab14272b07305f2f7c9 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Mon, 23 Mar 2009 11:57:46 -0600 Subject: [PATCH 004/211] gitk: Make more options easily accessible from Edit View dialog Commit 218a900bd8efd0d49f8a0d9491aa4786a998d4f4 added a number of new individual fields for the Edit View dialog to make them more accessible to end users, while still allowing all options to be specified in the "arguments to git log" field. This extends the dialog further, to include refs, author, committer, commit message, and patch contents. As before everything still remains accessible from the "arguments to git log" input field. Additionally, this provides hints for the format of the various input fields (for example, listing some sample date strings in different formats), and puts related query items into subsections to make it easier to digest the number of options that exist. Signed-off-by: Elijah Newren Signed-off-by: Paul Mackerras --- gitk | 131 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 37 deletions(-) diff --git a/gitk b/gitk index 5710782472..0804e6e36e 100755 --- a/gitk +++ b/gitk @@ -3671,17 +3671,35 @@ proc newview {ishighlight} { } set known_view_options { - {perm b . {} {mc "Remember this view"}} - {args t50= + {} {mc "Commits to include (arguments to git log):"}} - {all b * "--all" {mc "Use all refs"}} - {dorder b . {"--date-order" "-d"} {mc "Strictly sort by date"}} - {lright b . "--left-right" {mc "Mark branch sides"}} - {since t15 + {"--since=*" "--after=*"} {mc "Since date:"}} - {until t15 . {"--until=*" "--before=*"} {mc "Until date:"}} - {limit t10 + "--max-count=*" {mc "Max count:"}} - {skip t10 . "--skip=*" {mc "Skip:"}} - {first b . "--first-parent" {mc "Limit to first parent"}} - {cmd t50= + {} {mc "Command to generate more commits to include:"}} + {perm b . {} {mc "Remember this view"}} + {reflabel l + {} {mc "References (space separated list):"}} + {refs t15 .. {} {mc "Branches & tags:"}} + {allrefs b *. "--all" {mc "All refs"}} + {branches b . "--branches" {mc "All (local) branches"}} + {tags b . "--tags" {mc "All tags"}} + {remotes b . "--remotes" {mc "All remote-tracking branches"}} + {commitlbl l + {} {mc "Commit Info (regular expressions):"}} + {author t15 .. "--author=*" {mc "Author:"}} + {committer t15 . "--committer=*" {mc "Committer:"}} + {loginfo t15 .. "--grep=*" {mc "Commit Message:"}} + {allmatch b .. "--all-match" {mc "Matches all Commit Info criteria"}} + {changes_l l + {} {mc "Changes to Files:"}} + {pickaxe_s r0 . {} {mc "Fixed String"}} + {pickaxe_t r1 . "--pickaxe-regex" {mc "Regular Expression"}} + {pickaxe t15 .. "-S*" {mc "Search string:"}} + {datelabel l + {} {mc "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 15:27:38\"):"}} + {since t15 .. {"--since=*" "--after=*"} {mc "Since:"}} + {until t15 . {"--until=*" "--before=*"} {mc "Until:"}} + {limit_lbl l + {} {mc "Limit and/or skip a number of revisions (positive integer):"}} + {limit t10 *. "--max-count=*" {mc "Number to show:"}} + {skip t10 . "--skip=*" {mc "Number to skip:"}} + {misc_lbl l + {} {mc "Miscellaneous options:"}} + {dorder b *. {"--date-order" "-d"} {mc "Strictly sort by date"}} + {lright b . "--left-right" {mc "Mark branch sides"}} + {first b . "--first-parent" {mc "Limit to first parent"}} + {args t50 *. {} {mc "Additional arguments to git log:"}} + {allpaths path + {} {mc "Enter files and directories to include, one per line:"}} + {cmd t50= + {} {mc "Command to generate more commits to include:"}} } proc encode_view_opts {n} { @@ -3693,13 +3711,19 @@ proc encode_view_opts {n} { if {$patterns eq {}} continue set pattern [lindex $patterns 0] - set val $newviewopts($n,[lindex $opt 0]) - if {[lindex $opt 1] eq "b"} { + set val $newviewopts($n,[lindex $opt 0]) if {$val} { lappend rargs $pattern } + } elseif {[regexp {^r(\d+)$} [lindex $opt 1] type value]} { + regexp {^(.*_)} [lindex $opt 0] uselessvar button_id + set val $newviewopts($n,$button_id) + if {$val eq $value} { + lappend rargs $pattern + } } else { + set val $newviewopts($n,[lindex $opt 0]) set val [string trim $val] if {$val ne {}} { set pfix [string range $pattern 0 end-1] @@ -3707,6 +3731,7 @@ proc encode_view_opts {n} { } } } + set rargs [concat $rargs [shellsplit $newviewopts($n,refs)]] return [concat $rargs [shellsplit $newviewopts($n,args)]] } @@ -3714,14 +3739,22 @@ proc decode_view_opts {n view_args} { global known_view_options newviewopts foreach opt $known_view_options { + set id [lindex $opt 0] if {[lindex $opt 1] eq "b"} { + # Checkboxes + set val 0 + } elseif {[regexp {^r(\d+)$} [lindex $opt 1]]} { + # Radiobuttons + regexp {^(.*_)} $id uselessvar id set val 0 } else { + # Text fields set val {} } - set newviewopts($n,[lindex $opt 0]) $val + set newviewopts($n,$id) $val } set oargs [list] + set refargs [list] foreach arg $view_args { if {[regexp -- {^-([0-9]+)$} $arg arg cnt] && ![info exists found(limit)]} { @@ -3735,11 +3768,17 @@ proc decode_view_opts {n view_args} { if {[info exists found($id)]} continue foreach pattern [lindex $opt 3] { if {![string match $pattern $arg]} continue - if {[lindex $opt 1] ne "b"} { + if {[lindex $opt 1] eq "b"} { + # Check buttons + set val 1 + } elseif {[regexp {^r(\d+)$} [lindex $opt 1] match num]} { + # Radio buttons + regexp {^(.*_)} $id uselessvar id + set val $num + } else { + # Text input fields set size [string length $pattern] set val [string range $arg [expr {$size-1}] end] - } else { - set val 1 } set newviewopts($n,$id) $val set found($id) 1 @@ -3748,8 +3787,13 @@ proc decode_view_opts {n view_args} { if {[info exists val]} break } if {[info exists val]} continue - lappend oargs $arg + if {[regexp {^-} $arg]} { + lappend oargs $arg + } else { + lappend refargs $arg + } } + set newviewopts($n,refs) [shellarglist $refargs] set newviewopts($n,args) [shellarglist $oargs] } @@ -3785,16 +3829,16 @@ proc vieweditor {top n title} { global known_view_options toplevel $top - wm title $top $title + wm title $top [concat $title "-- criteria for selecting revisions"] make_transient $top . # View name frame $top.nfr - label $top.nl -text [mc "Name"] + label $top.nl -text [mc "View Name:"] entry $top.name -width 20 -textvariable newviewname($n) pack $top.nfr -in $top -fill x -pady 5 -padx 3 - pack $top.nl -in $top.nfr -side left -padx {0 30} - pack $top.name -in $top.nfr -side left + pack $top.nl -in $top.nfr -side left -padx {0 5} + pack $top.name -in $top.nfr -side left -padx {0 25} # View options set cframe $top.nfr @@ -3813,14 +3857,28 @@ proc vieweditor {top n title} { frame $cframe pack $cframe -in $top -fill x -pady 3 -padx 3 set cexpand [expr {$flags eq "*"}] + } elseif {$flags eq ".." || $flags eq "*."} { + set cframe $top.fr$cnt + incr cnt + frame $cframe + pack $cframe -in $top -fill x -pady 3 -padx [list 15 3] + set cexpand [expr {$flags eq "*."}] } else { set lxpad 5 } - if {$type eq "b"} { + if {$type eq "l"} { + label $cframe.l_$id -text $title + pack $cframe.l_$id -in $cframe -side left -pady [list 3 0] -anchor w + } elseif {$type eq "b"} { checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id) pack $cframe.c_$id -in $cframe -side left \ -padx [list $lxpad 0] -expand $cexpand -anchor w + } elseif {[regexp {^r(\d+)$} $type type sz]} { + regexp {^(.*_)} $id uselessvar button_id + radiobutton $cframe.c_$id -text $title -variable newviewopts($n,$button_id) -value $sz + pack $cframe.c_$id -in $cframe -side left \ + -padx [list $lxpad 0] -expand $cexpand -anchor w } elseif {[regexp {^t(\d+)$} $type type sz]} { message $cframe.l_$id -aspect 1500 -text $title entry $cframe.e_$id -width $sz -background $bgcolor \ @@ -3833,23 +3891,22 @@ proc vieweditor {top n title} { -textvariable newviewopts($n,$id) pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w pack $cframe.e_$id -in $cframe -side top -fill x + } elseif {$type eq "path"} { + message $top.l -aspect 1500 -text $title + pack $top.l -in $top -side top -pady [list 3 0] -anchor w -padx 3 + text $top.t -width 40 -height 5 -background $bgcolor -font uifont + if {[info exists viewfiles($n)]} { + foreach f $viewfiles($n) { + $top.t insert end $f + $top.t insert end "\n" + } + $top.t delete {end - 1c} end + $top.t mark set insert 0.0 + } + pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3 } } - # Path list - message $top.l -aspect 1500 \ - -text [mc "Enter files and directories to include, one per line:"] - pack $top.l -in $top -side top -pady [list 7 0] -anchor w -padx 3 - text $top.t -width 40 -height 5 -background $bgcolor -font uifont - if {[info exists viewfiles($n)]} { - foreach f $viewfiles($n) { - $top.t insert end $f - $top.t insert end "\n" - } - $top.t delete {end - 1c} end - $top.t mark set insert 0.0 - } - pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3 frame $top.buts button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n] button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1] From 194bbf6cc8c2f3c14a920c841841d66b7667a848 Mon Sep 17 00:00:00 2001 From: Pat Thoyts Date: Mon, 18 May 2009 22:46:01 +0100 Subject: [PATCH 005/211] gitk: Handle msysGit version during version comparisons msysGit generates version strings with text appended which cannot be used with vcompare; trying to use them generates a Tcl error. Limit git_version to the first three digits which are the real git version to avoid this error. Signed-off-by: Pat Thoyts Signed-off-by: Paul Mackerras --- gitk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitk b/gitk index 0804e6e36e..18553904f8 100755 --- a/gitk +++ b/gitk @@ -11152,7 +11152,7 @@ set nullid2 "0000000000000000000000000000000000000001" set nullfile "/dev/null" set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}] -set git_version [lindex [exec git version] end] +set git_version [join [lrange [split [lindex [exec git version] end] .] 0 2] .] set runq {} set history {} From d11b8d342529a8fe2164ceb563ad9213902d3533 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 20 May 2009 11:04:35 -0700 Subject: [PATCH 006/211] write-tree --ignore-cache-tree This allows you to discard the cache-tree information before writing the tree out of the index (i.e. it always recomputes the tree object names for all the subtrees). This is only useful as a debug option, so I did not bother documenting it. Signed-off-by: Junio C Hamano --- builtin-write-tree.c | 12 +++++++++--- cache-tree.c | 10 +++++++--- cache-tree.h | 7 ++++++- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/builtin-write-tree.c b/builtin-write-tree.c index 9d640508dd..3a24ce8157 100644 --- a/builtin-write-tree.c +++ b/builtin-write-tree.c @@ -13,7 +13,7 @@ static const char write_tree_usage[] = int cmd_write_tree(int argc, const char **argv, const char *unused_prefix) { - int missing_ok = 0, ret; + int flags = 0, ret; const char *prefix = NULL; unsigned char sha1[20]; const char *me = "git-write-tree"; @@ -22,9 +22,15 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix) while (1 < argc) { const char *arg = argv[1]; if (!strcmp(arg, "--missing-ok")) - missing_ok = 1; + flags |= WRITE_TREE_MISSING_OK; else if (!prefixcmp(arg, "--prefix=")) prefix = arg + 9; + else if (!prefixcmp(arg, "--ignore-cache-tree")) + /* + * This is only useful for debugging, so I + * do not bother documenting it. + */ + flags |= WRITE_TREE_IGNORE_CACHE_TREE; else usage(write_tree_usage); argc--; argv++; @@ -33,7 +39,7 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix) if (argc > 2) die("too many options"); - ret = write_cache_as_tree(sha1, missing_ok, prefix); + ret = write_cache_as_tree(sha1, flags, prefix); switch (ret) { case 0: printf("%s\n", sha1_to_hex(sha1)); diff --git a/cache-tree.c b/cache-tree.c index 37bf35e636..6dd8411945 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -538,28 +538,32 @@ static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *pat return it; } -int write_cache_as_tree(unsigned char *sha1, int missing_ok, const char *prefix) +int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix) { int entries, was_valid, newfd; + struct lock_file *lock_file; /* * We can't free this memory, it becomes part of a linked list * parsed atexit() */ - struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file)); + lock_file = xcalloc(1, sizeof(struct lock_file)); newfd = hold_locked_index(lock_file, 1); entries = read_cache(); if (entries < 0) return WRITE_TREE_UNREADABLE_INDEX; + if (flags & WRITE_TREE_IGNORE_CACHE_TREE) + cache_tree_free(&(active_cache_tree)); if (!active_cache_tree) active_cache_tree = cache_tree(); was_valid = cache_tree_fully_valid(active_cache_tree); - if (!was_valid) { + int missing_ok = flags & WRITE_TREE_MISSING_OK; + if (cache_tree_update(active_cache_tree, active_cache, active_nr, missing_ok, 0) < 0) diff --git a/cache-tree.h b/cache-tree.h index e958835236..eadcad8adc 100644 --- a/cache-tree.h +++ b/cache-tree.h @@ -30,11 +30,16 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size); int cache_tree_fully_valid(struct cache_tree *); int cache_tree_update(struct cache_tree *, struct cache_entry **, int, int, int); +/* bitmasks to write_cache_as_tree flags */ +#define WRITE_TREE_MISSING_OK 1 +#define WRITE_TREE_IGNORE_CACHE_TREE 2 + +/* error return codes */ #define WRITE_TREE_UNREADABLE_INDEX (-1) #define WRITE_TREE_UNMERGED_INDEX (-2) #define WRITE_TREE_PREFIX_ERROR (-3) -int write_cache_as_tree(unsigned char *sha1, int missing_ok, const char *prefix); +int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix); void prime_cache_tree(struct cache_tree **, struct tree *); #endif From f687aaa83371f0fd9aa41e62cd74405491ddab78 Mon Sep 17 00:00:00 2001 From: Dirk Suesserott Date: Thu, 21 May 2009 15:35:40 +0200 Subject: [PATCH 007/211] gitk: Add option 'Simple history' to the options menu When clicked, the option --simplify-by-decoration is added to gitk/git log. This yields to a simplified history where only decorated commits are shown, i.e. those with a yellow tag or a green branch flag. Signed-off-by: Dirk Suesserott Signed-off-by: Paul Mackerras --- gitk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gitk b/gitk index 18553904f8..d48fbad857 100755 --- a/gitk +++ b/gitk @@ -187,7 +187,8 @@ proc parseviewargs {n arglist} { "--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" - "--author=*" - "--committer=*" - "--grep=*" - "-[iE]" - "--remove-empty" - "--first-parent" - "--cherry-pick" - - "-S*" - "--pickaxe-all" - "--pickaxe-regex" { + "-S*" - "--pickaxe-all" - "--pickaxe-regex" - + "--simplify-by-decoration" { # These mean that we get a subset of the commits set filtered 1 lappend glflags $arg @@ -3697,6 +3698,7 @@ set known_view_options { {dorder b *. {"--date-order" "-d"} {mc "Strictly sort by date"}} {lright b . "--left-right" {mc "Mark branch sides"}} {first b . "--first-parent" {mc "Limit to first parent"}} + {smplhst b . "--simplify-by-decoration" {mc "Simple history"}} {args t50 *. {} {mc "Additional arguments to git log:"}} {allpaths path + {} {mc "Enter files and directories to include, one per line:"}} {cmd t50= + {} {mc "Command to generate more commits to include:"}} From e0a0199581ea30abb58ba812047657b35f4ee639 Mon Sep 17 00:00:00 2001 From: Michele Ballabio Date: Sat, 23 May 2009 11:48:25 +0200 Subject: [PATCH 008/211] gitk: Add another string to translation Signed-off-by: Michele Ballabio Signed-off-by: Paul Mackerras --- gitk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitk b/gitk index d48fbad857..72b0b0df7a 100755 --- a/gitk +++ b/gitk @@ -3831,7 +3831,7 @@ proc vieweditor {top n title} { global known_view_options toplevel $top - wm title $top [concat $title "-- criteria for selecting revisions"] + wm title $top [concat $title [mc "-- criteria for selecting revisions"]] make_transient $top . # View name From a41ddbb649c72214a4861827eedc7b2eebe0608f Mon Sep 17 00:00:00 2001 From: Markus Heidelberg Date: Sat, 23 May 2009 19:31:37 +0200 Subject: [PATCH 009/211] gitk: Allow diff view without context lines Signed-off-by: Markus Heidelberg Signed-off-by: Paul Mackerras --- gitk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gitk b/gitk index 72b0b0df7a..4604c831fe 100755 --- a/gitk +++ b/gitk @@ -2146,7 +2146,7 @@ proc makewindow {} { label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: " pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left spinbox .bleft.mid.diffcontext -width 5 -font textfont \ - -from 1 -increment 1 -to 10000000 \ + -from 0 -increment 1 -to 10000000 \ -validate all -validatecommand "diffcontextvalidate %P" \ -textvariable diffcontextstring .bleft.mid.diffcontext set $diffcontext @@ -7308,7 +7308,7 @@ proc diffcontextchange {n1 n2 op} { global diffcontextstring diffcontext if {[string is integer -strict $diffcontextstring]} { - if {$diffcontextstring > 0} { + if {$diffcontextstring >= 0} { set diffcontext $diffcontextstring reselectline } From b87fc96476c4218de044cf77b4c6d10d49aee78a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 20 May 2009 15:53:57 -0700 Subject: [PATCH 010/211] cache-tree.c::cache_tree_find(): simplify internal API Earlier cache_tree_find() needs to be called with a valid cache_tree, but repeated look-up may find an invalid or missing cache_tree in between. Help simplify the callers by returning NULL to mean "nothing appropriate found" when the input is NULL. Signed-off-by: Junio C Hamano --- cache-tree.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cache-tree.c b/cache-tree.c index 6dd8411945..5481e43340 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -514,6 +514,8 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size) static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *path) { + if (!it) + return NULL; while (*path) { const char *slash; struct cache_tree_sub *sub; From aceae2ef9261718324bf1853401d5ee9686a54a8 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 22 May 2009 23:06:58 -0700 Subject: [PATCH 011/211] t4007: modernize the style This is one of the oldest scripts; update it to match more modern style. Notably, we should: - Put the test title on the same line as the "test_expect_success", and end the line with a single-quote to begin the body of the test which is one multi-line string; and - Run as many commands inside test_expect_success, not outside, to catch unexpected breakages. Signed-off-by: Junio C Hamano --- t/t4007-rename-3.sh | 67 +++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh index 42072d724e..25e7a83659 100755 --- a/t/t4007-rename-3.sh +++ b/t/t4007-rename-3.sh @@ -9,32 +9,31 @@ test_description='Rename interaction with pathspec. . ./test-lib.sh . "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash -test_expect_success \ - 'prepare reference tree' \ - 'mkdir path0 path1 && - cp "$TEST_DIRECTORY"/../COPYING path0/COPYING && - git update-index --add path0/COPYING && - tree=$(git write-tree) && - echo $tree' +test_expect_success 'prepare reference tree' ' + mkdir path0 path1 && + cp "$TEST_DIRECTORY"/../COPYING path0/COPYING && + git update-index --add path0/COPYING && + tree=$(git write-tree) && + echo $tree +' -test_expect_success \ - 'prepare work tree' \ - 'cp path0/COPYING path1/COPYING && - git update-index --add --remove path0/COPYING path1/COPYING' +test_expect_success 'prepare work tree' ' + cp path0/COPYING path1/COPYING && + git update-index --add --remove path0/COPYING path1/COPYING +' # In the tree, there is only path0/COPYING. In the cache, path0 and # path1 both have COPYING and the latter is a copy of path0/COPYING. # Comparing the full tree with cache should tell us so. -git diff-index -C --find-copies-harder $tree >current - cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 6ff87c4664981e4397625791c8ea3bbb5f2279a3 C100 path0/COPYING path1/COPYING EOF -test_expect_success \ - 'validate the result (#1)' \ - 'compare_diff_raw current expected' +test_expect_success 'copy detection' ' + git diff-index -C --find-copies-harder $tree >current && + compare_diff_raw current expected +' # In the tree, there is only path0/COPYING. In the cache, path0 and # path1 both have COPYING and the latter is a copy of path0/COPYING. @@ -42,49 +41,45 @@ test_expect_success \ # path1/COPYING suddenly appearing from nowhere, not detected as # a copy from path0/COPYING. -git diff-index -C $tree path1 >current - cat >expected <<\EOF :000000 100644 0000000000000000000000000000000000000000 6ff87c4664981e4397625791c8ea3bbb5f2279a3 A path1/COPYING EOF -test_expect_success \ - 'validate the result (#2)' \ - 'compare_diff_raw current expected' - -test_expect_success \ - 'tweak work tree' \ - 'rm -f path0/COPYING && - git update-index --remove path0/COPYING' +test_expect_success 'copy, limited to a subtree' ' + git diff-index -C --find-copies-harder $tree path1 >current && + compare_diff_raw current expected +' +test_expect_success 'tweak work tree' ' + rm -f path0/COPYING && + git update-index --remove path0/COPYING +' # In the tree, there is only path0/COPYING. In the cache, path0 does # not have COPYING anymore and path1 has COPYING which is a copy of # path0/COPYING. Showing the full tree with cache should tell us about # the rename. -git diff-index -C $tree >current - cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 6ff87c4664981e4397625791c8ea3bbb5f2279a3 R100 path0/COPYING path1/COPYING EOF -test_expect_success \ - 'validate the result (#3)' \ - 'compare_diff_raw current expected' +test_expect_success 'rename detection' ' + git diff-index -C --find-copies-harder $tree >current && + compare_diff_raw current expected +' # In the tree, there is only path0/COPYING. In the cache, path0 does # not have COPYING anymore and path1 has COPYING which is a copy of # path0/COPYING. When we say we care only about path1, we should just # see path1/COPYING appearing from nowhere. -git diff-index -C $tree path1 >current - cat >expected <<\EOF :000000 100644 0000000000000000000000000000000000000000 6ff87c4664981e4397625791c8ea3bbb5f2279a3 A path1/COPYING EOF -test_expect_success \ - 'validate the result (#4)' \ - 'compare_diff_raw current expected' +test_expect_success 'rename, limited to a subtree' ' + git diff-index -C --find-copies-harder $tree path1 >current && + compare_diff_raw current expected +' test_done From b65982b60876c8f5f4d3b2898d5174f4812552b1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 20 May 2009 15:57:22 -0700 Subject: [PATCH 012/211] Optimize "diff-index --cached" using cache-tree When running "diff-index --cached" after making a change to only a small portion of the index, there is no point unpacking unchanged subtrees into the index recursively, only to find that all entries match anyway. Tweak unpack_trees() logic that is used to read in the tree object to catch the case where the tree entry we are looking at matches the index as a whole by looking at the cache-tree. As an exercise, after modifying a few paths in the kernel tree, here are a few numbers on my Athlon 64X2 3800+: (without patch, hot cache) $ /usr/bin/time git diff --cached --raw :100644 100644 b57e1f5... e69de29... M Makefile :100644 000000 8c86b72... 0000000... D arch/x86/Makefile :000000 100644 0000000... e69de29... A arche 0.07user 0.02system 0:00.09elapsed 102%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+9407minor)pagefaults 0swaps (with patch, hot cache) $ /usr/bin/time ../git.git/git-diff --cached --raw :100644 100644 b57e1f5... e69de29... M Makefile :100644 000000 8c86b72... 0000000... D arch/x86/Makefile :000000 100644 0000000... e69de29... A arche 0.02user 0.00system 0:00.02elapsed 103%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+2446minor)pagefaults 0swaps Cold cache numbers are very impressive, but it does not matter very much in practice: (without patch, cold cache) $ su root sh -c 'echo 3 >/proc/sys/vm/drop_caches' $ /usr/bin/time git diff --cached --raw :100644 100644 b57e1f5... e69de29... M Makefile :100644 000000 8c86b72... 0000000... D arch/x86/Makefile :000000 100644 0000000... e69de29... A arche 0.06user 0.17system 0:10.26elapsed 2%CPU (0avgtext+0avgdata 0maxresident)k 247032inputs+0outputs (1172major+8237minor)pagefaults 0swaps (with patch, cold cache) $ su root sh -c 'echo 3 >/proc/sys/vm/drop_caches' $ /usr/bin/time ../git.git/git-diff --cached --raw :100644 100644 b57e1f5... e69de29... M Makefile :100644 000000 8c86b72... 0000000... D arch/x86/Makefile :000000 100644 0000000... e69de29... A arche 0.02user 0.01system 0:01.01elapsed 3%CPU (0avgtext+0avgdata 0maxresident)k 18440inputs+0outputs (79major+2369minor)pagefaults 0swaps This of course helps "git status" as well. (without patch, hot cache) $ /usr/bin/time ../git.git/git-status >/dev/null 0.17user 0.18system 0:00.35elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+5336outputs (0major+10970minor)pagefaults 0swaps (with patch, hot cache) $ /usr/bin/time ../git.git/git-status >/dev/null 0.10user 0.16system 0:00.27elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+5336outputs (0major+3921minor)pagefaults 0swaps Signed-off-by: Junio C Hamano --- cache-tree.c | 32 ++++++++++++++++++++++++++++++++ cache-tree.h | 3 +++ diff-lib.c | 2 ++ unpack-trees.c | 17 +++++++++++++++++ unpack-trees.h | 1 + 5 files changed, 55 insertions(+) diff --git a/cache-tree.c b/cache-tree.c index 5481e43340..16a65dfac1 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -631,3 +631,35 @@ void prime_cache_tree(struct cache_tree **it, struct tree *tree) *it = cache_tree(); prime_cache_tree_rec(*it, tree); } + +/* + * find the cache_tree that corresponds to the current level without + * exploding the full path into textual form. The root of the + * cache tree is given as "root", and our current level is "info". + * (1) When at root level, info->prev is NULL, so it is "root" itself. + * (2) Otherwise, find the cache_tree that corresponds to one level + * above us, and find ourselves in there. + */ +static struct cache_tree *find_cache_tree_from_traversal(struct cache_tree *root, + struct traverse_info *info) +{ + struct cache_tree *our_parent; + + if (!info->prev) + return root; + our_parent = find_cache_tree_from_traversal(root, info->prev); + return cache_tree_find(our_parent, info->name.path); +} + +int cache_tree_matches_traversal(struct cache_tree *root, + struct name_entry *ent, + struct traverse_info *info) +{ + struct cache_tree *it; + + it = find_cache_tree_from_traversal(root, info); + it = cache_tree_find(it, ent->path); + if (it && it->entry_count > 0 && !hashcmp(ent->sha1, it->sha1)) + return it->entry_count; + return 0; +} diff --git a/cache-tree.h b/cache-tree.h index eadcad8adc..3df641f593 100644 --- a/cache-tree.h +++ b/cache-tree.h @@ -2,6 +2,7 @@ #define CACHE_TREE_H #include "tree.h" +#include "tree-walk.h" struct cache_tree; struct cache_tree_sub { @@ -42,4 +43,6 @@ int cache_tree_update(struct cache_tree *, struct cache_entry **, int, int, int) int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix); void prime_cache_tree(struct cache_tree **, struct tree *); +extern int cache_tree_matches_traversal(struct cache_tree *, struct name_entry *ent, struct traverse_info *info); + #endif diff --git a/diff-lib.c b/diff-lib.c index a310fb2ad0..1cb97af22d 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -446,6 +446,7 @@ int run_diff_index(struct rev_info *revs, int cached) memset(&opts, 0, sizeof(opts)); opts.head_idx = 1; opts.index_only = cached; + opts.diff_index_cached = cached; opts.merge = 1; opts.fn = oneway_diff; opts.unpack_data = revs; @@ -502,6 +503,7 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt) memset(&opts, 0, sizeof(opts)); opts.head_idx = 1; opts.index_only = 1; + opts.diff_index_cached = 1; opts.merge = 1; opts.fn = oneway_diff; opts.unpack_data = &revs; diff --git a/unpack-trees.c b/unpack-trees.c index aaacaf1015..8eb3ddb392 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -326,6 +326,23 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str if (src[0]) conflicts |= 1; } + + /* special case: "diff-index --cached" looking at a tree */ + if (o->diff_index_cached && + n == 1 && dirmask == 1 && S_ISDIR(names->mode)) { + int matches; + matches = cache_tree_matches_traversal(o->src_index->cache_tree, + names, info); + /* + * Everything under the name matches. Adjust o->pos to + * skip the entire hierarchy. + */ + if (matches) { + o->pos += matches; + return mask; + } + } + if (traverse_trees_recursive(n, dirmask, conflicts, names, info) < 0) return -1; diff --git a/unpack-trees.h b/unpack-trees.h index 0d26f3d73e..1e0e2325f1 100644 --- a/unpack-trees.h +++ b/unpack-trees.h @@ -27,6 +27,7 @@ struct unpack_trees_options { aggressive:1, skip_unmerged:1, initial_checkout:1, + diff_index_cached:1, gently:1; const char *prefix; int pos; From a0919ced8a5efe938cf97c74a0f851cbbe00aaf6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 22 May 2009 23:14:25 -0700 Subject: [PATCH 013/211] Avoid "diff-index --cached" optimization under --find-copies-harder When find-copies-harder is in effect, the diff frontends are expected to feed all paths, not just changed paths, to the diffcore, so that copy sources can be picked up. In such a case, not descending into subtrees using the cache-tree information is simply wrong. Signed-off-by: Junio C Hamano --- diff-lib.c | 5 +++-- t/t4007-rename-3.sh | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/diff-lib.c b/diff-lib.c index 1cb97af22d..ae75eacbcc 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -446,7 +446,8 @@ int run_diff_index(struct rev_info *revs, int cached) memset(&opts, 0, sizeof(opts)); opts.head_idx = 1; opts.index_only = cached; - opts.diff_index_cached = cached; + opts.diff_index_cached = (cached && + !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER)); opts.merge = 1; opts.fn = oneway_diff; opts.unpack_data = revs; @@ -503,7 +504,7 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt) memset(&opts, 0, sizeof(opts)); opts.head_idx = 1; opts.index_only = 1; - opts.diff_index_cached = 1; + opts.diff_index_cached = !DIFF_OPT_TST(opt, FIND_COPIES_HARDER); opts.merge = 1; opts.fn = oneway_diff; opts.unpack_data = &revs; diff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh index 25e7a83659..11502b7509 100755 --- a/t/t4007-rename-3.sh +++ b/t/t4007-rename-3.sh @@ -35,6 +35,11 @@ test_expect_success 'copy detection' ' compare_diff_raw current expected ' +test_expect_success 'copy detection, cached' ' + git diff-index -C --find-copies-harder --cached $tree >current && + compare_diff_raw current expected +' + # In the tree, there is only path0/COPYING. In the cache, path0 and # path1 both have COPYING and the latter is a copy of path0/COPYING. # However when we say we care only about path1, we should just see From a5a6755a1d4707bf2fab7752e5c974ebf63d086a Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Wed, 27 May 2009 11:25:16 +0200 Subject: [PATCH 014/211] git-am foreign patch support: introduce patch_format Set up a framework to allow git-am to support patches which are not in mailbox format. Introduce a patch_format variable that presently can only be set from the command line, defaulting to 'mbox' (the only supported format) if not specified. Signed-off-by: Junio C Hamano --- git-am.sh | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/git-am.sh b/git-am.sh index 578780be13..da160de3c3 100755 --- a/git-am.sh +++ b/git-am.sh @@ -18,6 +18,7 @@ whitespace= pass it through git-apply directory= pass it through git-apply C= pass it through git-apply p= pass it through git-apply +patch-format= format the patch(es) are in reject pass it through git-apply resolvemsg= override error message when patch failure occurs r,resolved to be used after a patch failure @@ -133,6 +134,32 @@ It does not apply to blobs recorded in its index." unset GITHEAD_$his_tree } +patch_format= + +check_patch_format () { + # early return if patch_format was set from the command line + if test -n "$patch_format" + then + return 0 + fi + patch_format=mbox +} + +split_patches () { + case "$patch_format" in + mbox) + git mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" || { + rm -fr "$dotest" + exit 1 + } + ;; + *) + echo "Patch format $patch_format is not supported." + exit 1 + ;; + esac +} + prec=4 dotest="$GIT_DIR/rebase-apply" sign= utf8=t keep= skip= interactive= resolved= rebasing= abort= @@ -175,6 +202,8 @@ do git_apply_opt="$git_apply_opt $(sq "$1=$2")"; shift ;; -C|-p) git_apply_opt="$git_apply_opt $(sq "$1$2")"; shift ;; + --patch-format) + shift ; patch_format="$1" ;; --reject) git_apply_opt="$git_apply_opt $1" ;; --committer-date-is-author-date) @@ -274,10 +303,10 @@ else done shift fi - git mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" || { - rm -fr "$dotest" - exit 1 - } + + check_patch_format "$@" + + split_patches "$@" # -s, -u, -k, --whitespace, -3, -C and -p flags are kept # for the resuming session after a patch failure. From 15ced753ac091314941abb28302f7109a9e86b81 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Wed, 27 May 2009 23:20:12 +0200 Subject: [PATCH 015/211] git-am foreign patch support: autodetect some patch formats Default to mbox format if input is from stdin. Otherwise, look at the first few lines of the first patch to try to guess its format. Include checks for mailboxes, stgit patch series, stgit single patches and hg patches. Signed-off-by: Junio C Hamano --- git-am.sh | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/git-am.sh b/git-am.sh index da160de3c3..552b888703 100755 --- a/git-am.sh +++ b/git-am.sh @@ -142,7 +142,45 @@ check_patch_format () { then return 0 fi - patch_format=mbox + + # we default to mbox format if input is from stdin and for + # directories + if test $# = 0 || test "x$1" = "x-" || test -d "$1" + then + patch_format=mbox + return 0 + fi + + # otherwise, check the first few lines of the first patch to try + # to detect its format + { + read l1 + read l2 + read l3 + case "$l1" in + "From "* | "From: "*) + patch_format=mbox + ;; + '# This series applies on GIT commit'*) + patch_format=stgit-series + ;; + "# HG changeset patch") + patch_format=hg + ;; + *) + # if the second line is empty and the third is + # a From, Author or Date entry, this is very + # likely an StGIT patch + case "$l2,$l3" in + ,"From: "* | ,"Author: "* | ,"Date: "*) + patch_format=stgit + ;; + *) + ;; + esac + ;; + esac + } < "$1" } split_patches () { From c574e683b587ee3c302317e4fa9c83cd4605cd82 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Wed, 27 May 2009 11:25:18 +0200 Subject: [PATCH 016/211] git-am foreign patch support: StGIT support Support StGIT patches by implementing a simple perl-based converter mimicking StGIT's own parse_patch. Also support StGIT patch series by 'exploding' the index into a list of files and re-running the mail splitting with patch_format set to stgit. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- git-am.sh | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/git-am.sh b/git-am.sh index 552b888703..0ff1f577a3 100755 --- a/git-am.sh +++ b/git-am.sh @@ -191,6 +191,63 @@ split_patches () { exit 1 } ;; + stgit-series) + if test $# -ne 1 + then + echo "Only one StGIT patch series can be applied at once" + exit 1 + fi + series_dir=`dirname "$1"` + series_file="$1" + shift + { + set x + while read filename + do + set "$@" "$series_dir/$filename" + done + # remove the safety x + shift + # remove the arg coming from the first-line comment + shift + } < "$series_file" + # set the patch format appropriately + patch_format=stgit + # now handle the actual StGIT patches + split_patches "$@" + ;; + stgit) + this=0 + for stgit in "$@" + do + this=`expr "$this" + 1` + msgnum=`printf "%0${prec}d" $this` + # Perl version of StGIT parse_patch. The first nonemptyline + # not starting with Author, From or Date is the + # subject, and the body starts with the next nonempty + # line not starting with Author, From or Date + perl -ne 'BEGIN { $subject = 0 } + if ($subject > 1) { print ; } + elsif (/^\s+$/) { next ; } + elsif (/^Author:/) { print s/Author/From/ ; } + elsif (/^(From|Date)/) { print ; } + elsif ($subject) { + $subject = 2 ; + print "\n" ; + print ; + } else { + print "Subject: ", $_ ; + $subject = 1; + } + ' < "$stgit" > "$dotest/$msgnum" || { + echo "Failed to import $patch_format patch $stgit" + exit 1 + } + done + echo "$this" > "$dotest/last" + this= + msgnum= + ;; *) echo "Patch format $patch_format is not supported." exit 1 From 42b491786260eb17d97ea9fb1c4b70075bca9523 Mon Sep 17 00:00:00 2001 From: Johan Herland Date: Wed, 3 Jun 2009 00:59:12 +0200 Subject: [PATCH 017/211] git-submodule: add support for --merge. 'git submodule update --merge' merges the commit referenced by the superproject into your local branch, instead of checking it out on a detached HEAD. As evidenced by the addition of "git submodule update --rebase", it is useful to provide alternatives to the default 'checkout' behaviour of "git submodule update". One such alternative is, when updating a submodule to a new commit, to merge that commit into the current local branch in that submodule. This is useful in workflows where you want to update your submodule from its upstream, but you cannot use --rebase, because you have downstream people working on top of your submodule branch, and you don't want to disrupt their work. Signed-off-by: Johan Herland Signed-off-by: Junio C Hamano --- Documentation/git-submodule.txt | 15 +++++++-- Documentation/gitmodules.txt | 6 ++-- git-submodule.sh | 11 +++++- t/t7406-submodule-update.sh | 60 ++++++++++++++++++++++++++++++++- 4 files changed, 86 insertions(+), 6 deletions(-) diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt index f993469dc6..2289d11f0e 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@ -113,8 +113,9 @@ init:: update:: Update the registered submodules, i.e. clone missing submodules and checkout the commit specified in the index of the containing repository. - This will make the submodules HEAD be detached unless '--rebase' is - specified or the key `submodule.$name.update` is set to `rebase`. + This will make the submodules HEAD be detached unless '--rebase' or + '--merge' is specified or the key `submodule.$name.update` is set to + `rebase` or `merge`. + If the submodule is not yet initialized, and you just want to use the setting as stored in .gitmodules, you can automatically initialize the @@ -187,6 +188,16 @@ OPTIONS If the key `submodule.$name.update` is set to `rebase`, this option is implicit. +--merge:: + This option is only valid for the update command. + Merge the commit recorded in the superproject into the current branch + of the submodule. If this option is given, the submodule's HEAD will + not be detached. If a merge failure prevents this process, you will + have to resolve the resulting conflicts within the submodule with the + usual conflict resolution tools. + If the key `submodule.$name.update` is set to `merge`, this option is + implicit. + ...:: Paths to submodule(s). When specified this will restrict the command to only operate on the submodules found at the specified paths. diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt index 1b67f0a9f1..5daf750d19 100644 --- a/Documentation/gitmodules.txt +++ b/Documentation/gitmodules.txt @@ -35,9 +35,11 @@ submodule..update:: If 'checkout' (the default), the new commit specified in the superproject will be checked out in the submodule on a detached HEAD. If 'rebase', the current branch of the submodule will be rebased onto - the commit specified in the superproject. + the commit specified in the superproject. If 'merge', the commit + specified in the superproject will be merged into the current branch + in the submodule. This config option is overridden if 'git submodule update' is given - the '--rebase' option. + the '--merge' or '--rebase' options. EXAMPLES diff --git a/git-submodule.sh b/git-submodule.sh index f384c6b2b4..3aff37970a 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -5,7 +5,7 @@ # Copyright (c) 2007 Lars Hjemli USAGE="[--quiet] [--cached] \ -[add [-b branch] ]|[status|init|update [-i|--init] [-N|--no-fetch]|summary [-n|--summary-limit ] []] \ +[add [-b branch] ]|[status|init|update [-i|--init] [-N|--no-fetch] [--rebase|--merge]|summary [-n|--summary-limit ] []] \ [--] [...]|[foreach ]|[sync [--] [...]]" OPTIONS_SPEC= . git-sh-setup @@ -331,6 +331,10 @@ cmd_update() shift update="rebase" ;; + -m|--merge) + shift + update="merge" + ;; --) shift break @@ -396,6 +400,11 @@ cmd_update() action="rebase" msg="rebased onto" ;; + merge) + command="git merge" + action="merge" + msg="merged in" + ;; *) command="git checkout $force -q" action="checkout" diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 0773fe405b..2d33d9efec 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -6,7 +6,7 @@ test_description='Test updating submodules This test verifies that "git submodule update" detaches the HEAD of the -submodule and "git submodule update --rebase" does not detach the HEAD. +submodule and "git submodule update --rebase/--merge" does not detach the HEAD. ' . ./test-lib.sh @@ -76,6 +76,20 @@ test_expect_success 'submodule update --rebase staying on master' ' ) ' +test_expect_success 'submodule update --merge staying on master' ' + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update --merge submodule && + cd submodule && + compare_head + ) +' + test_expect_success 'submodule update - rebase in .git/config' ' (cd super && git config submodule.submodule.update rebase @@ -110,6 +124,40 @@ test_expect_success 'submodule update - checkout in .git/config but --rebase giv ) ' +test_expect_success 'submodule update - merge in .git/config' ' + (cd super && + git config submodule.submodule.update merge + ) && + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update submodule && + cd submodule && + compare_head + ) +' + +test_expect_success 'submodule update - checkout in .git/config but --merge given' ' + (cd super && + git config submodule.submodule.update checkout + ) && + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update --merge submodule && + cd submodule && + compare_head + ) +' + test_expect_success 'submodule update - checkout in .git/config' ' (cd super && git config submodule.submodule.update checkout @@ -137,4 +185,14 @@ test_expect_success 'submodule init picks up rebase' ' ) ' +test_expect_success 'submodule init picks up merge' ' + (cd super && + git config submodule.merging.url git://non-existing/git && + git config submodule.merging.path does-not-matter && + git config submodule.merging.update merge && + git submodule init merging && + test "merge" = $(git config submodule.merging.update) + ) +' + test_done From 934f82a7d424ea9a8fa0ae83020689d11efc2bff Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Mon, 8 Jun 2009 20:46:38 -0700 Subject: [PATCH 018/211] fix handling of iconv configuration options Fix the way in which the configure script handles --without-iconv (and --with-iconv=no), which it used to essentially ignore. Also fix the way the configure script determines the value of NEEDS_LIBICONV, which would be incorrectly set to 'YesPlease' on systems that lack iconv entirely. Signed-off-by: Marco Nelissen Signed-off-by: Junio C Hamano --- configure.ac | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configure.ac b/configure.ac index 4e728bca35..25fbe3bb6b 100644 --- a/configure.ac +++ b/configure.ac @@ -385,6 +385,8 @@ AC_SUBST(NO_EXPAT) # some Solaris installations). # Define NO_ICONV if neither libc nor libiconv support iconv. +if test -z "$NO_ICONV"; then + GIT_STASH_FLAGS($ICONVDIR) AC_DEFUN([ICONVTEST_SRC], [ @@ -431,6 +433,12 @@ GIT_UNSTASH_FLAGS($ICONVDIR) AC_SUBST(NEEDS_LIBICONV) AC_SUBST(NO_ICONV) +if test -n "$NO_ICONV"; then + NEEDS_LIBICONV= +fi + +fi + # # Define NO_DEFLATE_BOUND if deflateBound is missing from zlib. From 203462347fce0eab563fe77640648a7e8ae64d3b Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Tue, 9 Jun 2009 18:01:34 +0200 Subject: [PATCH 019/211] Allow push and fetch urls to be different This introduces a config setting remote.$remotename.pushurl which is used for pushes only. If absent remote.$remotename.url is used for pushes and fetches as before. This is useful, for example, in order to do passwordless fetches (remote update) over the git transport but pushes over ssh. Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- Documentation/config.txt | 3 +++ Documentation/urls-remotes.txt | 3 +++ builtin-push.c | 17 +++++++++++++---- remote.c | 14 ++++++++++++++ remote.h | 4 ++++ 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 3a86d1f8f0..2fecbe32a6 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1319,6 +1319,9 @@ remote..url:: The URL of a remote repository. See linkgit:git-fetch[1] or linkgit:git-push[1]. +remote..pushurl:: + The push URL of a remote repository. See linkgit:git-push[1]. + remote..proxy:: For remotes that require curl (http, https and ftp), the URL to the proxy to use for that remote. Set to the empty string to diff --git a/Documentation/urls-remotes.txt b/Documentation/urls-remotes.txt index 41ec7774f4..2a0e7b8944 100644 --- a/Documentation/urls-remotes.txt +++ b/Documentation/urls-remotes.txt @@ -27,10 +27,13 @@ config file would appear like this: ------------ [remote ""] url = + pushurl = push = fetch = ------------ +The `` is used for pushes only. It is optional and defaults +to ``. Named file in `$GIT_DIR/remotes` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/builtin-push.c b/builtin-push.c index c869974013..7be12399b6 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -117,6 +117,8 @@ static int do_push(const char *repo, int flags) { int i, errs; struct remote *remote = remote_get(repo); + const char **url; + int url_nr; if (!remote) { if (repo) @@ -152,9 +154,16 @@ static int do_push(const char *repo, int flags) setup_default_push_refspecs(); } errs = 0; - for (i = 0; i < remote->url_nr; i++) { + if (remote->pushurl_nr) { + url = remote->pushurl; + url_nr = remote->pushurl_nr; + } else { + url = remote->url; + url_nr = remote->url_nr; + } + for (i = 0; i < url_nr; i++) { struct transport *transport = - transport_get(remote, remote->url[i]); + transport_get(remote, url[i]); int err; if (receivepack) transport_set_option(transport, @@ -163,14 +172,14 @@ static int do_push(const char *repo, int flags) transport_set_option(transport, TRANS_OPT_THIN, "yes"); if (flags & TRANSPORT_PUSH_VERBOSE) - fprintf(stderr, "Pushing to %s\n", remote->url[i]); + fprintf(stderr, "Pushing to %s\n", url[i]); err = transport_push(transport, refspec_nr, refspec, flags); err |= transport_disconnect(transport); if (!err) continue; - error("failed to push some refs to '%s'", remote->url[i]); + error("failed to push some refs to '%s'", url[i]); errs++; } return !!errs; diff --git a/remote.c b/remote.c index 2c3e9053a4..4544d65c72 100644 --- a/remote.c +++ b/remote.c @@ -106,6 +106,12 @@ static void add_url_alias(struct remote *remote, const char *url) add_url(remote, alias_url(url)); } +static void add_pushurl(struct remote *remote, const char *pushurl) +{ + ALLOC_GROW(remote->pushurl, remote->pushurl_nr + 1, remote->pushurl_alloc); + remote->pushurl[remote->pushurl_nr++] = pushurl; +} + static struct remote *make_remote(const char *name, int len) { struct remote *ret; @@ -379,6 +385,11 @@ static int handle_config(const char *key, const char *value, void *cb) if (git_config_string(&v, key, value)) return -1; add_url(remote, v); + } else if (!strcmp(subkey, ".pushurl")) { + const char *v; + if (git_config_string(&v, key, value)) + return -1; + add_pushurl(remote, v); } else if (!strcmp(subkey, ".push")) { const char *v; if (git_config_string(&v, key, value)) @@ -424,6 +435,9 @@ static void alias_all_urls(void) for (j = 0; j < remotes[i]->url_nr; j++) { remotes[i]->url[j] = alias_url(remotes[i]->url[j]); } + for (j = 0; j < remotes[i]->pushurl_nr; j++) { + remotes[i]->pushurl[j] = alias_url(remotes[i]->pushurl[j]); + } } } diff --git a/remote.h b/remote.h index 99706a89bc..326bffeb0c 100644 --- a/remote.h +++ b/remote.h @@ -15,6 +15,10 @@ struct remote { int url_nr; int url_alloc; + const char **pushurl; + int pushurl_nr; + int pushurl_alloc; + const char **push_refspec; struct refspec *push; int push_refspec_nr; From e1ca424112d5e8923a4a83af0f79eadbff088b69 Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Tue, 9 Jun 2009 18:01:35 +0200 Subject: [PATCH 020/211] t5516: Check pushurl config setting Check whether the new remote.${remotename}.pushurl setting is obeyed and whether it overrides remote.${remotename}.url. Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- t/t5516-fetch-push.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 89649e7a9b..2d2633f3f8 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -419,6 +419,19 @@ test_expect_success 'push with config remote.*.push = HEAD' ' git config --remove-section remote.there git config --remove-section branch.master +test_expect_success 'push with config remote.*.pushurl' ' + + mk_test heads/master && + git checkout master && + git config remote.there.url test2repo && + git config remote.there.pushurl testrepo && + git push there && + check_push_result $the_commit heads/master +' + +# clean up the cruft left with the previous one +git config --remove-section remote.there + test_expect_success 'push with dry-run' ' mk_test heads/master && From 056724c6240ce79ff5ef4e91191bf7366dadba88 Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Tue, 9 Jun 2009 18:01:36 +0200 Subject: [PATCH 021/211] technical/api-remote: Describe new struct remote member pushurl ...and pushurl_nr Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- Documentation/technical/api-remote.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/technical/api-remote.txt b/Documentation/technical/api-remote.txt index 073b22bd83..c54b17db69 100644 --- a/Documentation/technical/api-remote.txt +++ b/Documentation/technical/api-remote.txt @@ -18,6 +18,10 @@ struct remote An array of all of the url_nr URLs configured for the remote +`pushurl`:: + + An array of all of the pushurl_nr push URLs configured for the remote + `push`:: An array of refspecs configured for pushing, with From 97af7ff0553ed81bb905dbc0c8b0f9a0c10bfb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santi=20B=C3=A9jar?= Date: Fri, 12 Jun 2009 00:39:18 +0200 Subject: [PATCH 022/211] parse-remote: function to get the tracking branch to be merge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only user of get_remote_refs_for_fetch was "git pull --rebase" and it only wanted the tracking branch to be merge. So, add a simple function (get_remote_merge_branch) with this new meaning. No behavior changes. The new function behaves like the old code in "git pull --rebase". In particular, it only works with the default refspec mapping and with remote branches, not tags. Signed-off-by: Santi Béjar Signed-off-by: Junio C Hamano --- git-parse-remote.sh | 29 +++++++++++++++++++++++++++++ git-pull.sh | 7 ++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/git-parse-remote.sh b/git-parse-remote.sh index a296719861..a991564b95 100755 --- a/git-parse-remote.sh +++ b/git-parse-remote.sh @@ -229,6 +229,34 @@ get_remote_refs_for_fetch () { esac } +get_remote_merge_branch () { + case "$#" in + 0|1) + die "internal error: get-remote-merge-branch." ;; + *) + repo=$1 + shift + ref=$1 + # FIXME: It should return the tracking branch + # Currently only works with the default mapping + case "$ref" in + +*) + ref=$(expr "z$ref" : 'z+\(.*\)') + ;; + esac + expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:" + remote=$(expr "z$ref" : 'z\([^:]*\):') + case "$remote" in + '' | HEAD ) remote=HEAD ;; + heads/*) remote=${remote#heads/} ;; + refs/heads/*) remote=${remote#refs/heads/} ;; + refs/* | tags/* | remotes/* ) remote= + esac + + [ -n "$remote" ] && echo "refs/remotes/$repo/$remote" + esac +} + resolve_alternates () { # original URL (xxx.git) top_=`expr "z$1" : 'z\([^:]*:/*[^/]*\)/'` @@ -262,3 +290,4 @@ get_uploadpack () { ;; esac } + diff --git a/git-pull.sh b/git-pull.sh index 35261539ab..3cf26634ad 100755 --- a/git-pull.sh +++ b/git-pull.sh @@ -125,12 +125,9 @@ test true = "$rebase" && { die "refusing to pull with rebase: your working tree is not up-to-date" . git-parse-remote && - origin="$1" - test -z "$origin" && origin=$(get_default_remote) - reflist="$(get_remote_refs_for_fetch "$@" 2>/dev/null | - sed "s|refs/heads/\(.*\):|\1|")" && + reflist="$(get_remote_merge_branch "$@" 2>/dev/null)" && oldremoteref="$(git rev-parse -q --verify \ - "refs/remotes/$origin/$reflist")" + "$reflist")" } orig_head=$(git rev-parse -q --verify HEAD) git fetch $verbosity --update-head-ok "$@" || exit 1 From e9460a66e0d11b718757cd88eb0c927f2b79e1c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santi=20B=C3=A9jar?= Date: Fri, 12 Jun 2009 00:39:19 +0200 Subject: [PATCH 023/211] parse-remote: support default reflist in get_remote_merge_branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expand get_remote_merge_branch to compute the tracking branch to merge when called without arguments (or only the remote name). This allows "git pull --rebase" without arguments (default upstream branch) to work with a rebased upstream. With explicit arguments it already worked. Also add a test to check for this case. Signed-off-by: Santi Béjar Signed-off-by: Junio C Hamano --- git-parse-remote.sh | 8 +++++++- t/t5520-pull.sh | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/git-parse-remote.sh b/git-parse-remote.sh index a991564b95..75e1254640 100755 --- a/git-parse-remote.sh +++ b/git-parse-remote.sh @@ -232,7 +232,13 @@ get_remote_refs_for_fetch () { get_remote_merge_branch () { case "$#" in 0|1) - die "internal error: get-remote-merge-branch." ;; + origin="$1" + default=$(get_default_remote) + test -z "$origin" && origin=$default + curr_branch=$(git symbolic-ref -q HEAD) + [ "$origin" = "$default" ] && + echo $(git for-each-ref --format='%(upstream)' $curr_branch) + ;; *) repo=$1 shift diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 725771fac1..c5a2e66a09 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -92,20 +92,34 @@ test_expect_success '--rebase with rebased upstream' ' git remote add -f me . && git checkout copy && + git tag copy-orig && git reset --hard HEAD^ && echo conflicting modification > file && git commit -m conflict file && git checkout to-rebase && echo file > file2 && git commit -m to-rebase file2 && + git tag to-rebase-orig && git pull --rebase me copy && test "conflicting modification" = "$(cat file)" && test file = $(cat file2) ' +test_expect_success '--rebase with rebased default upstream' ' + + git update-ref refs/remotes/me/copy copy-orig && + git checkout --track -b to-rebase2 me/copy && + git reset --hard to-rebase-orig && + git pull --rebase && + test "conflicting modification" = "$(cat file)" && + test file = $(cat file2) + +' + test_expect_success 'pull --rebase dies early with dirty working directory' ' + git checkout to-rebase && git update-ref refs/remotes/me/copy copy^ && COPY=$(git rev-parse --verify me/copy) && git rebase --onto $COPY copy && From 62d955fd435273dcd9fffed0c0d83bbe90006a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santi=20B=C3=A9jar?= Date: Fri, 12 Jun 2009 00:39:21 +0200 Subject: [PATCH 024/211] parse-remote: remove unused functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Santi Béjar Signed-off-by: Junio C Hamano --- Documentation/git-parse-remote.txt | 20 --- git-parse-remote.sh | 204 ----------------------------- 2 files changed, 224 deletions(-) diff --git a/Documentation/git-parse-remote.txt b/Documentation/git-parse-remote.txt index cd43069874..39d9daa7e0 100644 --- a/Documentation/git-parse-remote.txt +++ b/Documentation/git-parse-remote.txt @@ -17,26 +17,6 @@ routines to parse files under $GIT_DIR/remotes/ and $GIT_DIR/branches/ and configuration variables that are related to fetching, pulling and pushing. -The primary entry points are: - -get_remote_refs_for_fetch:: - Given the list of user-supplied ` ...`, - return the list of refs to fetch after canonicalizing - them into `$GIT_DIR` relative paths - (e.g. `refs/heads/foo`). When `...` is empty - the returned list of refs consists of the defaults - for the given ``, if specified in - `$GIT_DIR/remotes/`, `$GIT_DIR/branches/`, or `remote.*.fetch` - configuration. - -get_remote_refs_for_push:: - Given the list of user-supplied ` ...`, - return the list of refs to push in a form suitable to be - fed to the 'git-send-pack' command. When `...` - is empty the returned list of refs consists of the - defaults for the given ``, if specified in - `$GIT_DIR/remotes/`. - Author ------ Written by Junio C Hamano. diff --git a/git-parse-remote.sh b/git-parse-remote.sh index 75e1254640..5f47b18141 100755 --- a/git-parse-remote.sh +++ b/git-parse-remote.sh @@ -60,175 +60,6 @@ get_default_remote () { echo ${origin:-origin} } -get_remote_default_refs_for_push () { - data_source=$(get_data_source "$1") - case "$data_source" in - '' | branches | self) - ;; # no default push mapping, just send matching refs. - config) - git config --get-all "remote.$1.push" ;; - remotes) - sed -ne '/^Push: */{ - s///p - }' "$GIT_DIR/remotes/$1" ;; - *) - die "internal error: get-remote-default-ref-for-push $1" ;; - esac -} - -# Called from canon_refs_list_for_fetch -d "$remote", which -# is called from get_remote_default_refs_for_fetch to grok -# refspecs that are retrieved from the configuration, but not -# from get_remote_refs_for_fetch when it deals with refspecs -# supplied on the command line. $ls_remote_result has the list -# of refs available at remote. -# -# The first token returned is either "explicit" or "glob"; this -# is to help prevent randomly "globbed" ref from being chosen as -# a merge candidate -expand_refs_wildcard () { - echo "$ls_remote_result" | - git fetch--tool expand-refs-wildcard "-" "$@" -} - -# Subroutine to canonicalize remote:local notation. -canon_refs_list_for_fetch () { - # If called from get_remote_default_refs_for_fetch - # leave the branches in branch.${curr_branch}.merge alone, - # or the first one otherwise; add prefix . to the rest - # to prevent the secondary branches to be merged by default. - merge_branches= - curr_branch= - if test "$1" = "-d" - then - shift ; remote="$1" ; shift - set $(expand_refs_wildcard "$remote" "$@") - is_explicit="$1" - shift - if test "$remote" = "$(get_default_remote)" - then - curr_branch=$(git symbolic-ref -q HEAD | \ - sed -e 's|^refs/heads/||') - merge_branches=$(git config \ - --get-all "branch.${curr_branch}.merge") - fi - if test -z "$merge_branches" && test $is_explicit != explicit - then - merge_branches=..this.will.never.match.any.ref.. - fi - fi - for ref - do - force= - case "$ref" in - +*) - ref=$(expr "z$ref" : 'z+\(.*\)') - force=+ - ;; - esac - expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:" - remote=$(expr "z$ref" : 'z\([^:]*\):') - local=$(expr "z$ref" : 'z[^:]*:\(.*\)') - dot_prefix=. - if test -z "$merge_branches" - then - merge_branches=$remote - dot_prefix= - else - for merge_branch in $merge_branches - do - [ "$remote" = "$merge_branch" ] && - dot_prefix= && break - done - fi - case "$remote" in - '' | HEAD ) remote=HEAD ;; - refs/*) ;; - heads/* | tags/* | remotes/* ) remote="refs/$remote" ;; - *) remote="refs/heads/$remote" ;; - esac - case "$local" in - '') local= ;; - refs/*) ;; - heads/* | tags/* | remotes/* ) local="refs/$local" ;; - *) local="refs/heads/$local" ;; - esac - - if local_ref_name=$(expr "z$local" : 'zrefs/\(.*\)') - then - git check-ref-format "$local_ref_name" || - die "* refusing to create funny ref '$local_ref_name' locally" - fi - echo "${dot_prefix}${force}${remote}:${local}" - done -} - -# Returns list of src: (no store), or src:dst (store) -get_remote_default_refs_for_fetch () { - data_source=$(get_data_source "$1") - case "$data_source" in - '') - echo "HEAD:" ;; - self) - canon_refs_list_for_fetch -d "$1" \ - $(git for-each-ref --format='%(refname):') - ;; - config) - canon_refs_list_for_fetch -d "$1" \ - $(git config --get-all "remote.$1.fetch") ;; - branches) - remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1") - case "$remote_branch" in '') remote_branch=master ;; esac - echo "refs/heads/${remote_branch}:refs/heads/$1" - ;; - remotes) - canon_refs_list_for_fetch -d "$1" $(sed -ne '/^Pull: */{ - s///p - }' "$GIT_DIR/remotes/$1") - ;; - *) - die "internal error: get-remote-default-ref-for-fetch $1" ;; - esac -} - -get_remote_refs_for_push () { - case "$#" in - 0) die "internal error: get-remote-refs-for-push." ;; - 1) get_remote_default_refs_for_push "$@" ;; - *) shift; echo "$@" ;; - esac -} - -get_remote_refs_for_fetch () { - case "$#" in - 0) - die "internal error: get-remote-refs-for-fetch." ;; - 1) - get_remote_default_refs_for_fetch "$@" ;; - *) - shift - tag_just_seen= - for ref - do - if test "$tag_just_seen" - then - echo "refs/tags/${ref}:refs/tags/${ref}" - tag_just_seen= - continue - else - case "$ref" in - tag) - tag_just_seen=yes - continue - ;; - esac - fi - canon_refs_list_for_fetch "$ref" - done - ;; - esac -} - get_remote_merge_branch () { case "$#" in 0|1) @@ -262,38 +93,3 @@ get_remote_merge_branch () { [ -n "$remote" ] && echo "refs/remotes/$repo/$remote" esac } - -resolve_alternates () { - # original URL (xxx.git) - top_=`expr "z$1" : 'z\([^:]*:/*[^/]*\)/'` - while read path - do - case "$path" in - \#* | '') - continue ;; - /*) - echo "$top_$path/" ;; - ../*) - # relative -- ugly but seems to work. - echo "$1/objects/$path/" ;; - *) - # exit code may not be caught by the reader. - echo "bad alternate: $path" - exit 1 ;; - esac - done -} - -get_uploadpack () { - data_source=$(get_data_source "$1") - case "$data_source" in - config) - uplp=$(git config --get "remote.$1.uploadpack") - echo ${uplp:-git-upload-pack} - ;; - *) - echo "git-upload-pack" - ;; - esac -} - From 857f8c30d79ce15b6110b0df9d3ad87075ca5153 Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Sat, 13 Jun 2009 18:29:10 +0200 Subject: [PATCH 025/211] builtin-remote: Show push urls as well Teach builtin remote to show push urls also when asked to "show" a specific remote. This improves upon the standard display mode: multiple specified "url"s mean that the first one is for fetching, all are used for pushing. We make this clearer now by displaying the first one prefixed with "Fetch URL", and all "url"s (or, if present, all "pushurl"s) prefixed with "Push URL". Example with "one" having one url, "two" two urls, "three" one url and one pushurl (URL part only): * remote one Fetch URL: hostone.com:/somepath/repoone.git Push URL: hostone.com:/somepath/repoone.git * remote two Fetch URL: hosttwo.com:/somepath/repotwo.git Push URL: hosttwo.com:/somepath/repotwo.git Push URL: hosttwobackup.com:/somewheresafe/repotwo.git * remote three Fetch URL: http://hostthree.com/otherpath/repothree.git Push URL: hostthree.com:/pathforpushes/repothree.git Also, adjust t5505 accordingly and make it test for the new output. Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- builtin-remote.c | 20 +++++++++++++++----- t/t5505-remote.sh | 10 +++++++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/builtin-remote.c b/builtin-remote.c index d7ab6b2d5f..8dcc6a4bf9 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -1002,15 +1002,25 @@ static int show(int argc, const char **argv) info.list = &info_list; for (; argc; argc--, argv++) { int i; + const char **url; + int url_nr; get_remote_ref_states(*argv, &states, query_flag); printf("* remote %s\n", *argv); - if (states.remote->url_nr) { - for (i=0; i < states.remote->url_nr; i++) - printf(" URL: %s\n", states.remote->url[i]); - } else - printf(" URL: %s\n", "(no URL)"); + printf(" Fetch URL: %s\n", states.remote->url_nr > 0 ? + states.remote->url[0] : "(no URL)"); + if (states.remote->pushurl_nr) { + url = states.remote->pushurl; + url_nr = states.remote->pushurl_nr; + } else { + url = states.remote->url; + url_nr = states.remote->url_nr; + } + for (i=0; i < url_nr; i++) + printf(" Push URL: %s\n", url[i]); + if (!i) + printf(" Push URL: %s\n", "(no URL)"); if (no_query) printf(" HEAD branch: (not queried)\n"); else if (!states.heads.nr) diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index e70246b3fb..852ccb5d7d 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -135,7 +135,8 @@ EOF cat > test/expect << EOF * remote origin - URL: $(pwd)/one + Fetch URL: $(pwd)/one + Push URL: $(pwd)/one HEAD branch: master Remote branches: master new (next fetch will store in remotes/origin) @@ -151,7 +152,8 @@ cat > test/expect << EOF master pushes to master (local out of date) master pushes to upstream (create) * remote two - URL: ../two + Fetch URL: ../two + Push URL: ../three HEAD branch (remote HEAD is ambiguous, may be one of the following): another master @@ -173,6 +175,7 @@ test_expect_success 'show' ' git branch --track rebase origin/master && git branch -d -r origin/master && git config --add remote.two.url ../two && + git config --add remote.two.pushurl ../three && git config branch.rebase.rebase true && git config branch.octopus.merge "topic-a topic-b topic-c" && (cd ../one && @@ -191,7 +194,8 @@ test_expect_success 'show' ' cat > test/expect << EOF * remote origin - URL: $(pwd)/one + Fetch URL: $(pwd)/one + Push URL: $(pwd)/one HEAD branch: (not queried) Remote branches: (status not queried) master From 4a4b4cdaabde477514c4938b60961538e1d2d91f Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Sat, 13 Jun 2009 18:29:11 +0200 Subject: [PATCH 026/211] builtin-remote: Make "remote -v" display push urls Currently, "remote -v" simply lists all urls so that one has to remember that only the first one is used for fetches, and all are used for pushes. Change this so that the role of an url is displayed in parentheses, and also display push urls. Example with "one" having one url, "two" two urls, "three" one url and one pushurl: one hostone.com:/somepath/repoone.git (fetch) one hostone.com:/somepath/repoone.git (push) three http://hostthree.com/otherpath/repothree.git (fetch) three hostthree.com:/pathforpushes/repothree.git (push) two hosttwo.com:/somepath/repotwo.git (fetch) two hosttwo.com:/somepath/repotwo.git (push) two hosttwobackup.com:/somewheresafe/repotwo.git (push) Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- builtin-remote.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/builtin-remote.c b/builtin-remote.c index 8dcc6a4bf9..3f6f5c2318 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -1279,14 +1279,31 @@ static int update(int argc, const char **argv) static int get_one_entry(struct remote *remote, void *priv) { struct string_list *list = priv; + const char **url; + int i, url_nr; + void **utilp; if (remote->url_nr > 0) { - int i; - - for (i = 0; i < remote->url_nr; i++) - string_list_append(remote->name, list)->util = (void *)remote->url[i]; + utilp = &(string_list_append(remote->name, list)->util); + *utilp = malloc(strlen(remote->url[0])+strlen(" (fetch)")+1); + strcpy((char *) *utilp, remote->url[0]); + strcat((char *) *utilp, " (fetch)"); } else string_list_append(remote->name, list)->util = NULL; + if (remote->pushurl_nr) { + url = remote->pushurl; + url_nr = remote->pushurl_nr; + } else { + url = remote->url; + url_nr = remote->url_nr; + } + for (i = 0; i < url_nr; i++) + { + utilp = &(string_list_append(remote->name, list)->util); + *utilp = malloc(strlen(url[i])+strlen(" (push)")+1); + strcpy((char *) *utilp, url[i]); + strcat((char *) *utilp, " (push)"); + } return 0; } @@ -1294,7 +1311,10 @@ static int get_one_entry(struct remote *remote, void *priv) static int show_all(void) { struct string_list list = { NULL, 0, 0 }; - int result = for_each_remote(get_one_entry, &list); + int result; + + list.strdup_strings = 1; + result = for_each_remote(get_one_entry, &list); if (!result) { int i; @@ -1312,6 +1332,7 @@ static int show_all(void) } } } + string_list_clear(&list, 1); return result; } From ebc9529f0358bdb10192fa27bc75f5d4e452ce90 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 13 Jun 2009 07:21:06 +0200 Subject: [PATCH 027/211] bisect: use a PRNG with a bias when skipping away from untestable commits Using a PRNG (pseudo random number generator) with a bias should be better than alternating between 3 fixed ratios. In repositories with many untestable commits it should prevent alternating between areas where many commits are untestable. The bias should favor commits that can give more information, so that the bisection process should not loose much efficiency. HPA suggested to use a PRNG and found that the best bias is to raise a ratio between 0 and 1 given by the PRNG to the power 1.5. An integer square root function is implemented to avoid including and linking with -lm. A PRNG function is implemented to get the same number sequence on different machines as suggested by "man 3 rand". Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- bisect.c | 50 +++++++++++++++++++++++++++++-------- t/t6030-bisect-porcelain.sh | 4 +-- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/bisect.c b/bisect.c index 6fdff05722..095b55eba6 100644 --- a/bisect.c +++ b/bisect.c @@ -585,16 +585,49 @@ struct commit_list *filter_skipped(struct commit_list *list, return filtered; } -static struct commit_list *apply_skip_ratio(struct commit_list *list, - int count, - int skip_num, int skip_denom) +#define PRN_MODULO 32768 + +/* + * This is a pseudo random number generator based on "man 3 rand". + * It is not used properly because the seed is the argument and it + * is increased by one between each call, but that should not matter + * for this application. + */ +int get_prn(int count) { + count = count * 1103515245 + 12345; + return ((unsigned)(count/65536) % PRN_MODULO); +} + +/* + * Custom integer square root from + * http://en.wikipedia.org/wiki/Integer_square_root + */ +static int sqrti(int val) +{ + float d, x = val; + + if (val == 0) + return 0; + + do { + float y = (x + (float)val / x) / 2; + d = (y > x) ? y - x : x - y; + x = y; + } while (d >= 0.5); + + return (int)x; +} + +static struct commit_list *skip_away(struct commit_list *list, int count) { - int index, i; struct commit_list *cur, *previous; + int prn, index, i; + + prn = get_prn(count); + index = (count * prn / PRN_MODULO) * sqrti(prn) / sqrti(PRN_MODULO); cur = list; previous = NULL; - index = count * skip_num / skip_denom; for (i = 0; cur; cur = cur->next, i++) { if (i == index) { @@ -614,7 +647,6 @@ static struct commit_list *managed_skipped(struct commit_list *list, struct commit_list **tried) { int count, skipped_first; - int skip_num, skip_denom; *tried = NULL; @@ -626,11 +658,7 @@ static struct commit_list *managed_skipped(struct commit_list *list, if (!skipped_first) return list; - /* Use alternatively 1/5, 2/5 and 3/5 as skip ratio. */ - skip_num = count % 3 + 1; - skip_denom = 5; - - return apply_skip_ratio(list, count, skip_num, skip_denom); + return skip_away(list, count); } static void bisect_rev_setup(struct rev_info *revs, const char *prefix, diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 4556cdd8d2..1315bab595 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -563,8 +563,8 @@ test_expect_success 'skipping away from skipped commit' ' hash7=$(git rev-parse --verify HEAD) && test "$hash7" = "$HASH7" && git bisect skip && - hash3=$(git rev-parse --verify HEAD) && - test "$hash3" = "$HASH3" + para3=$(git rev-parse --verify HEAD) && + test "$para3" = "$PARA_HASH3" ' # From 32d86ca53195590f8d7df9f5f58683c9a924d5af Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 13 Jun 2009 13:11:02 +0200 Subject: [PATCH 028/211] Documentation: remove warning saying that "git bisect skip" may slow bisection This warning was probably useless anyway, but it is even more so now that filtering of skipped commits is done in C and that there is a mechanism to skip away from broken commits. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- Documentation/git-bisect.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index ffc02c737c..63e7a42cb3 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -164,9 +164,8 @@ to do it for you by issuing the command: $ git bisect skip # Current version cannot be tested ------------ -But computing the commit to test may be slower afterwards and git may -eventually not be able to tell the first bad commit among a bad commit -and one or more skipped commits. +But git may eventually be unable to tell the first bad commit among +a bad commit and one or more skipped commits. You can even skip a range of commits, instead of just one commit, using the "''..''" notation. For example: From df533f34a31890a43baaf00d03c0a7fa51886bc5 Mon Sep 17 00:00:00 2001 From: Nick Edelen Date: Sat, 13 Jun 2009 17:06:09 -0700 Subject: [PATCH 029/211] diff-tree -r -t: include added/removed directories in the output We used to include only the modified and typechanged directories in the ouptut, but for consistency's sake, we should also include added and removed ones as well. This makes the output more consistent, but it may break existing scripts that expect to see the current output which has long been the established behaviour. Signed-off-by: Nick Edelen Signed-off-by: Junio C Hamano --- t/t4037-diff-r-t-dirs.sh | 53 ++++++++++++++++++++++++++++++++++++++++ tree-diff.c | 6 +++++ 2 files changed, 59 insertions(+) create mode 100755 t/t4037-diff-r-t-dirs.sh diff --git a/t/t4037-diff-r-t-dirs.sh b/t/t4037-diff-r-t-dirs.sh new file mode 100755 index 0000000000..f5ce3b29a2 --- /dev/null +++ b/t/t4037-diff-r-t-dirs.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +test_description='diff -r -t shows directory additions and deletions' + +. ./test-lib.sh + +test_expect_success setup ' + mkdir dc dr dt && + >dc/1 && + >dr/2 && + >dt/3 && + >fc && + >fr && + >ft && + git add . && + test_tick && + git commit -m initial && + + rm -fr dt dr ft fr && + mkdir da ft && + for p in dc/1 da/4 dt ft/5 fc + do + echo hello >$p || exit + done && + git add -u && + git add . && + test_tick && + git commit -m second +' + +cat >expect <<\EOF +A da +A da/4 +M dc +M dc/1 +D dr +D dr/2 +A dt +D dt +D dt/3 +M fc +D fr +D ft +A ft +A ft/5 +EOF + +test_expect_success verify ' + git diff-tree -r -t --name-status HEAD^ HEAD >actual && + test_cmp expect actual +' + +test_done diff --git a/tree-diff.c b/tree-diff.c index 9f67af6c1f..c83a8da392 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -233,6 +233,12 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree if (!tree || type != OBJ_TREE) die("corrupt tree sha %s", sha1_to_hex(sha1)); + if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) { + newbase[baselen + pathlen] = 0; + opt->add_remove(opt, *prefix, mode, sha1, newbase); + newbase[baselen + pathlen] = '/'; + } + init_tree_desc(&inner, tree, size); show_tree(opt, prefix, &inner, newbase, baselen + 1 + pathlen); From 824af25ace464177820fc69c19fc03ae4fc9e4b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 14 Jun 2009 01:58:42 +0200 Subject: [PATCH 030/211] more tests for git rev-parse --parse-opt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Junio C Hamano --- t/t1502-rev-parse-parseopt.sh | 38 +++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh index 997002d4c4..be0959e8a3 100755 --- a/t/t1502-rev-parse-parseopt.sh +++ b/t/t1502-rev-parse-parseopt.sh @@ -20,8 +20,7 @@ Extras EOF -test_expect_success 'test --parseopt help output' ' - git rev-parse --parseopt -- -h 2> output.err < optionspec << EOF some-command [options] ... some-command does foo and bar! @@ -37,7 +36,42 @@ C? option C with an optional argument Extras extra1 line above used to cause a segfault but no longer does EOF + +test_expect_success 'test --parseopt help output' ' + git rev-parse --parseopt -- -h 2> output.err < optionspec test_cmp expect.err output.err ' +cat > expect < output && + test_cmp expect output +' + +test_expect_success 'test --parseopt with mixed options and arguments' ' + git rev-parse --parseopt -- --foo arg --bar=ham < optionspec > output && + test_cmp expect output +' + +cat > expect < output && + test_cmp expect output +' + +cat > expect < output && + test_cmp expect output +' + test_done From 6e0800ef2575751f2e20d11e2cfe305304e5e9b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 14 Jun 2009 01:58:43 +0200 Subject: [PATCH 031/211] parse-opt: make PARSE_OPT_STOP_AT_NON_OPTION available to git rev-parse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Junio C Hamano --- Documentation/git-rev-parse.txt | 5 +++++ builtin-rev-parse.c | 8 ++++++-- t/t1502-rev-parse-parseopt.sh | 5 +++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 4bbdd056da..82045a2522 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -30,6 +30,11 @@ OPTIONS Only meaningful in `--parseopt` mode. Tells the option parser to echo out the first `--` met instead of skipping it. +--stop-at-non-option:: + Only meaningful in `--parseopt` mode. Lets the option parser stop at + the first non-option argument. This can be used to parse sub-commands + that take options themself. + --sq-quote:: Use 'git-rev-parse' in shell quoting mode (see SQ-QUOTE section below). In contrast to the `--sq` option below, this diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c index 112d622cda..5ea7518b0f 100644 --- a/builtin-rev-parse.c +++ b/builtin-rev-parse.c @@ -301,7 +301,7 @@ static const char *skipspaces(const char *s) static int cmd_parseopt(int argc, const char **argv, const char *prefix) { - static int keep_dashdash = 0; + static int keep_dashdash = 0, stop_at_non_option = 0; static char const * const parseopt_usage[] = { "git rev-parse --parseopt [options] -- [...]", NULL @@ -309,6 +309,9 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix) static struct option parseopt_opts[] = { OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash, "keep the `--` passed as an arg"), + OPT_BOOLEAN(0, "stop-at-non-option", &stop_at_non_option, + "stop parsing after the " + "first non-option argument"), OPT_END(), }; @@ -394,7 +397,8 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix) ALLOC_GROW(opts, onb + 1, osz); memset(opts + onb, 0, sizeof(opts[onb])); argc = parse_options(argc, argv, prefix, opts, usage, - keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0); + keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0 | + stop_at_non_option ? PARSE_OPT_STOP_AT_NON_OPTION : 0); strbuf_addf(&parsed, " --"); sq_quote_argv(&parsed, argv, 0); diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh index be0959e8a3..e504058062 100755 --- a/t/t1502-rev-parse-parseopt.sh +++ b/t/t1502-rev-parse-parseopt.sh @@ -65,6 +65,11 @@ test_expect_success 'test --parseopt with --' ' test_cmp expect output ' +test_expect_success 'test --parseopt --stop-at-non-option' ' + git rev-parse --parseopt --stop-at-non-option -- --foo arg --bar=ham < optionspec > output && + test_cmp expect output +' + cat > expect < Date: Wed, 27 May 2009 11:25:19 +0200 Subject: [PATCH 032/211] git-am: refactor 'cleaning up and aborting' Introduce a clean_abort function that echoes an optional error message to standard error, removes the dotest directory and exits with status 1. Use it when patch format detection or patch splitting fails early. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- git-am.sh | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/git-am.sh b/git-am.sh index 0ff1f577a3..327807ddcb 100755 --- a/git-am.sh +++ b/git-am.sh @@ -134,6 +134,12 @@ It does not apply to blobs recorded in its index." unset GITHEAD_$his_tree } +clean_abort () { + test $# = 0 || echo >&2 "$@" + rm -fr "$dotest" + exit 1 +} + patch_format= check_patch_format () { @@ -180,22 +186,19 @@ check_patch_format () { esac ;; esac - } < "$1" + } < "$1" || clean_abort } split_patches () { case "$patch_format" in mbox) - git mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" || { - rm -fr "$dotest" - exit 1 - } + git mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" || + clean_abort ;; stgit-series) if test $# -ne 1 then - echo "Only one StGIT patch series can be applied at once" - exit 1 + clean_abort "Only one StGIT patch series can be applied at once" fi series_dir=`dirname "$1"` series_file="$1" @@ -210,7 +213,7 @@ split_patches () { shift # remove the arg coming from the first-line comment shift - } < "$series_file" + } < "$series_file" || clean_abort # set the patch format appropriately patch_format=stgit # now handle the actual StGIT patches @@ -239,18 +242,14 @@ split_patches () { print "Subject: ", $_ ; $subject = 1; } - ' < "$stgit" > "$dotest/$msgnum" || { - echo "Failed to import $patch_format patch $stgit" - exit 1 - } + ' < "$stgit" > "$dotest/$msgnum" || clean_abort done echo "$this" > "$dotest/last" this= msgnum= ;; *) - echo "Patch format $patch_format is not supported." - exit 1 + clean_abort "Patch format $patch_format is not supported." ;; esac } From ce61595ea7eb3df22f6a943a38a273141f1af978 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Sun, 14 Jun 2009 21:46:10 +0200 Subject: [PATCH 033/211] avoid NULL dereference on failed malloc * builtin-remote.c (get_one_entry): Use xmalloc, not malloc. Signed-off-by: Jim Meyering Signed-off-by: Junio C Hamano --- builtin-remote.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builtin-remote.c b/builtin-remote.c index 3f6f5c2318..fd0e63c5dc 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -1285,7 +1285,7 @@ static int get_one_entry(struct remote *remote, void *priv) if (remote->url_nr > 0) { utilp = &(string_list_append(remote->name, list)->util); - *utilp = malloc(strlen(remote->url[0])+strlen(" (fetch)")+1); + *utilp = xmalloc(strlen(remote->url[0])+strlen(" (fetch)")+1); strcpy((char *) *utilp, remote->url[0]); strcat((char *) *utilp, " (fetch)"); } else @@ -1300,7 +1300,7 @@ static int get_one_entry(struct remote *remote, void *priv) for (i = 0; i < url_nr; i++) { utilp = &(string_list_append(remote->name, list)->util); - *utilp = malloc(strlen(url[i])+strlen(" (push)")+1); + *utilp = xmalloc(strlen(url[i])+strlen(" (push)")+1); strcpy((char *) *utilp, url[i]); strcat((char *) *utilp, " (push)"); } From 90dce51584e908232ff279a6c2949ea9855dddf3 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Sun, 14 Jun 2009 21:47:54 +0200 Subject: [PATCH 034/211] use xstrdup, not strdup in ll-merge.c Otherwise, a fluky allocation failure would cause merge configuration settings to be silently ignored. Signed-off-by: Jim Meyering Signed-off-by: Junio C Hamano --- ll-merge.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ll-merge.c b/ll-merge.c index 9837c842a3..e339b8cfac 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -233,7 +233,7 @@ static int read_merge_config(const char *var, const char *value, void *cb) if (!strcmp(var, "merge.default")) { if (value) - default_ll_merge = strdup(value); + default_ll_merge = xstrdup(value); return 0; } @@ -267,7 +267,7 @@ static int read_merge_config(const char *var, const char *value, void *cb) if (!strcmp("name", ep)) { if (!value) return error("%s: lacks value", var); - fn->description = strdup(value); + fn->description = xstrdup(value); return 0; } @@ -290,14 +290,14 @@ static int read_merge_config(const char *var, const char *value, void *cb) * file named by %A, and signal that it has done with zero exit * status. */ - fn->cmdline = strdup(value); + fn->cmdline = xstrdup(value); return 0; } if (!strcmp("recursive", ep)) { if (!value) return error("%s: lacks value", var); - fn->recursive = strdup(value); + fn->recursive = xstrdup(value); return 0; } From 48fb7deb5bbd87933e7d314b73d7c1b52667f80f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 17 Jun 2009 17:22:27 -0700 Subject: [PATCH 035/211] Fix big left-shifts of unsigned char Shifting 'unsigned char' or 'unsigned short' left can result in sign extension errors, since the C integer promotion rules means that the unsigned char/short will get implicitly promoted to a signed 'int' due to the shift (or due to other operations). This normally doesn't matter, but if you shift things up sufficiently, it will now set the sign bit in 'int', and a subsequent cast to a bigger type (eg 'long' or 'unsigned long') will now sign-extend the value despite the original expression being unsigned. One example of this would be something like unsigned long size; unsigned char c; size += c << 24; where despite all the variables being unsigned, 'c << 24' ends up being a signed entity, and will get sign-extended when then doing the addition in an 'unsigned long' type. Since git uses 'unsigned char' pointers extensively, we actually have this bug in a couple of places. I may have missed some, but this is the result of looking at git grep '[^0-9 ][ ]*<<[ ][a-z]' -- '*.c' '*.h' git grep '<<[ ]*24' which catches at least the common byte cases (shifting variables by a variable amount, and shifting by 24 bits). I also grepped for just 'unsigned char' variables in general, and converted the ones that most obviously ended up getting implicitly cast immediately anyway (eg hash_name(), encode_85()). In addition to just avoiding 'unsigned char', this patch also tries to use a common idiom for the delta header size thing. We had three different variations on it: "& 0x7fUL" in one place (getting the sign extension right), and "& ~0x80" and "& 0x7f" in two other places (not getting it right). Apart from making them all just avoid using "unsigned char" at all, I also unified them to then use a simple "& 0x7f". I considered making a sparse extension which warns about doing implicit casts from unsigned types to signed types, but it gets rather complex very quickly, so this is just a hack. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- attr.c | 3 +-- base85.c | 2 +- builtin-pack-objects.c | 3 +-- builtin-unpack-objects.c | 4 ++-- delta.h | 5 ++--- index-pack.c | 6 +++--- patch-delta.c | 2 +- sha1_file.c | 3 +-- 8 files changed, 12 insertions(+), 16 deletions(-) diff --git a/attr.c b/attr.c index 98eb636f13..f8f6faa94f 100644 --- a/attr.c +++ b/attr.c @@ -35,8 +35,7 @@ static struct git_attr *(git_attr_hash[HASHSIZE]); static unsigned hash_name(const char *name, int namelen) { - unsigned val = 0; - unsigned char c; + unsigned val = 0, c; while (namelen--) { c = *name++; diff --git a/base85.c b/base85.c index b88270f908..b417a15bbc 100644 --- a/base85.c +++ b/base85.c @@ -91,7 +91,7 @@ void encode_85(char *buf, const unsigned char *data, int bytes) unsigned acc = 0; int cnt; for (cnt = 24; cnt >= 0; cnt -= 8) { - int ch = *data++; + unsigned ch = *data++; acc |= ch << cnt; if (--bytes == 0) break; diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 9742b45c4d..941cc2d73c 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -653,8 +653,7 @@ static void rehash_objects(void) static unsigned name_hash(const char *name) { - unsigned char c; - unsigned hash = 0; + unsigned c, hash = 0; if (!name) return 0; diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index 9a773239ca..8e831be476 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -422,8 +422,8 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size, static void unpack_one(unsigned nr) { unsigned shift; - unsigned char *pack, c; - unsigned long size; + unsigned char *pack; + unsigned long size, c; enum object_type type; obj_list[nr].offset = consumed_bytes; diff --git a/delta.h b/delta.h index 40ccf5a1e9..b9d333dd5a 100644 --- a/delta.h +++ b/delta.h @@ -90,12 +90,11 @@ static inline unsigned long get_delta_hdr_size(const unsigned char **datap, const unsigned char *top) { const unsigned char *data = *datap; - unsigned char cmd; - unsigned long size = 0; + unsigned long cmd, size = 0; int i = 0; do { cmd = *data++; - size |= (cmd & ~0x80) << i; + size |= (cmd & 0x7f) << i; i += 7; } while (cmd & 0x80 && data < top); *datap = data; diff --git a/index-pack.c b/index-pack.c index 6e93ee6af6..0c92bafcbb 100644 --- a/index-pack.c +++ b/index-pack.c @@ -293,8 +293,8 @@ static void *unpack_entry_data(unsigned long offset, unsigned long size) static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_base) { - unsigned char *p, c; - unsigned long size; + unsigned char *p; + unsigned long size, c; off_t base_offset; unsigned shift; void *data; @@ -312,7 +312,7 @@ static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_ p = fill(1); c = *p; use(1); - size += (c & 0x7fUL) << shift; + size += (c & 0x7f) << shift; shift += 7; } obj->size = size; diff --git a/patch-delta.c b/patch-delta.c index ed9db81fa8..ef748ce96d 100644 --- a/patch-delta.c +++ b/patch-delta.c @@ -44,7 +44,7 @@ void *patch_delta(const void *src_buf, unsigned long src_size, if (cmd & 0x01) cp_off = *data++; if (cmd & 0x02) cp_off |= (*data++ << 8); if (cmd & 0x04) cp_off |= (*data++ << 16); - if (cmd & 0x08) cp_off |= (*data++ << 24); + if (cmd & 0x08) cp_off |= ((unsigned) *data++ << 24); if (cmd & 0x10) cp_size = *data++; if (cmd & 0x20) cp_size |= (*data++ << 8); if (cmd & 0x40) cp_size |= (*data++ << 16); diff --git a/sha1_file.c b/sha1_file.c index e73cd4fc0b..8f5fe62d54 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1162,8 +1162,7 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep) { unsigned shift; - unsigned char c; - unsigned long size; + unsigned long size, c; unsigned long used = 0; c = buf[used++]; From b3c32ead20bc4d3baa6cffe00dd862f069463869 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 16 Jun 2009 15:32:57 -0700 Subject: [PATCH 036/211] t4150: test applying with a newline in subject Commit 4b7cc26 (git-am: use printf instead of echo on user-supplied strings, 2007-05-25) fixed a bug where subjects with newlines would cause git-am to echo multiple lines when it says "Applying: ". This test ensures that fix stays valid. Signed-off-by: Stephen Boyd Signed-off-by: Junio C Hamano --- t/t4150-am.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/t/t4150-am.sh b/t/t4150-am.sh index d6ebbaebe2..51c369ad14 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -305,4 +305,12 @@ test_expect_success 'am into an unborn branch' ' test "z$result" = "z$(git rev-parse first^{tree})" ' +test_expect_success 'am newline in subject' ' + git checkout first && + test_tick && + sed -e "s/second/second \\\n foo/" patch1 > patchnl && + git am < patchnl > output.out 2>&1 && + grep "^Applying: second \\\n foo$" output.out +' + test_done From 3ddd170323fcf24af8c4a321ed9c73cda532986e Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 16 Jun 2009 15:32:58 -0700 Subject: [PATCH 037/211] am: suppress apply errors when using 3-way git-am with 3-way outputs errors when applying, even though the 3-way will usually be successful. We suppress these errors from git-apply because they are not "true" errors until the 3-way has been attempted. Signed-off-by: Stephen Boyd Signed-off-by: Junio C Hamano --- git-am.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/git-am.sh b/git-am.sh index 578780be13..e26c54a3e2 100755 --- a/git-am.sh +++ b/git-am.sh @@ -502,7 +502,14 @@ do case "$resolved" in '') - eval 'git apply '"$git_apply_opt"' --index "$dotest/patch"' + # When we are allowed to fall back to 3-way later, don't give + # false errors during the initial attempt. + squelch= + if test "$threeway" = t + then + squelch='>/dev/null 2>&1 ' + fi + eval "git apply $squelch$git_apply_opt"' --index "$dotest/patch"' apply_status=$? ;; t) From e064c170b4abe21f50658f2ec3b07e4ec7520767 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 16 Jun 2009 15:32:59 -0700 Subject: [PATCH 038/211] git-sh-setup: introduce say() for quiet options Scripts should use say() when they want to output non-error messages. This function helps future script writers easily implement a quiet option by setting GIT_QUIET to enable suppression of non-error messages. Signed-off-by: Stephen Boyd Signed-off-by: Junio C Hamano --- git-sh-setup.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 80acb7de72..c41c2f7439 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -44,6 +44,15 @@ die() { exit 1 } +GIT_QUIET= + +say () { + if test -z "$GIT_QUIET" + then + printf '%s\n' "$*" + fi +} + if test -n "$OPTIONS_SPEC"; then usage() { "$0" -h From 2e6a30ef8fbaedc5f2ee199d36f7256bb0cfdf1e Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 16 Jun 2009 15:33:00 -0700 Subject: [PATCH 039/211] submodule, repack: migrate to git-sh-setup's say() Now that there is say() in git-sh-setup, these scripts don't need to use their own. Migrate them over by setting GIT_QUIET and removing their custom say() functions. Signed-off-by: Stephen Boyd Signed-off-by: Junio C Hamano --- git-repack.sh | 12 +++++------- git-submodule.sh | 24 ++++++------------------ 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/git-repack.sh b/git-repack.sh index 0868734723..1bf239499c 100755 --- a/git-repack.sh +++ b/git-repack.sh @@ -24,7 +24,7 @@ SUBDIRECTORY_OK='Yes' . git-sh-setup no_update_info= all_into_one= remove_redundant= unpack_unreachable= -local= quiet= no_reuse= extra= +local= no_reuse= extra= while test $# != 0 do case "$1" in @@ -33,7 +33,7 @@ do -A) all_into_one=t unpack_unreachable=--unpack-unreachable ;; -d) remove_redundant=t ;; - -q) quiet=-q ;; + -q) GIT_QUIET=t ;; -f) no_reuse=--no-reuse-object ;; -l) local=--local ;; --max-pack-size|--window|--window-memory|--depth) @@ -80,13 +80,11 @@ case ",$all_into_one," in ;; esac -args="$args $local $quiet $no_reuse$extra" +args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra" names=$(git pack-objects --honor-pack-keep --non-empty --all --reflog $args Date: Wed, 17 Jun 2009 16:26:06 +0200 Subject: [PATCH 040/211] avoid exponential regex match for java and objc function names In the old regex ^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\([^;]*)$ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ you can backtrack arbitrarily from [A-Za-z_0-9]* into [A-Za-z_], thus causing an exponential number of backtracks. Ironically it also causes the regex not to work as intended; for example "catch" can match the underlined part of the regex, the first repetition matching "c" and the second matching "atch". The replacement regex avoids this problem, because it makes sure that at least a space/tab is eaten on each repetition. In other words, a suffix of a repetition can never be a prefix of the next repetition. Signed-off-by: Paolo Bonzini Signed-off-by: Junio C Hamano --- userdiff.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/userdiff.c b/userdiff.c index d556da9751..57529ae63d 100644 --- a/userdiff.c +++ b/userdiff.c @@ -13,7 +13,8 @@ PATTERNS("html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$", "[^<>= \t]+|[^[:space:]]|[\x80-\xff]+"), PATTERNS("java", "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n" - "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$", + "^[ \t]*(([A-Za-z_][A-Za-z_0-9]*[ \t]+)+[A-Za-z_][A-Za-z_0-9]*[ \t]*\\([^;]*)$", + /* -- */ "[a-zA-Z_][a-zA-Z0-9_]*" "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?" "|[-+*/<>%&^|=!]=" @@ -25,7 +26,7 @@ PATTERNS("objc", /* Objective-C methods */ "^[ \t]*([-+][ \t]*\\([ \t]*[A-Za-z_][A-Za-z_0-9* \t]*\\)[ \t]*[A-Za-z_].*)$\n" /* C functions */ - "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$\n" + "^[ \t]*(([A-Za-z_][A-Za-z_0-9]*[ \t]+)+[A-Za-z_][A-Za-z_0-9]*[ \t]*\\([^;]*)$\n" /* Objective-C class/protocol definitions */ "^(@(implementation|interface|protocol)[ \t].*)$", /* -- */ From 1b19fa46344f512949270dc88089574950519ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Wed, 17 Jun 2009 12:11:10 +0200 Subject: [PATCH 041/211] upload-archive: fix infinite loop on Cygwin On Cygwin, poll() reports POLLIN even for file descriptors that have reached their end. This caused git upload-archive to be stuck in an infinite loop, as it only looked at the POLLIN flag. In addition to POLLIN, check if read() returned 0, which indicates end-of-file, and keep looping only as long as at least one of the file descriptors has input. This lets the following command finish on its own when run in a git repository on Cygwin, instead of it getting stuck after printing all file names: $ git archive -v --remote . HEAD >/dev/null Reported-by: Bob Kagy Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- builtin-upload-archive.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/builtin-upload-archive.c b/builtin-upload-archive.c index a9b02fa32f..f6c4c0f149 100644 --- a/builtin-upload-archive.c +++ b/builtin-upload-archive.c @@ -80,16 +80,17 @@ static void error_clnt(const char *fmt, ...) die("sent error to the client: %s", buf); } -static void process_input(int child_fd, int band) +static ssize_t process_input(int child_fd, int band) { char buf[16384]; ssize_t sz = read(child_fd, buf, sizeof(buf)); if (sz < 0) { if (errno != EAGAIN && errno != EINTR) error_clnt("read error: %s\n", strerror(errno)); - return; + return sz; } send_sideband(1, band, buf, sz, LARGE_PACKET_MAX); + return sz; } int cmd_upload_archive(int argc, const char **argv, const char *prefix) @@ -131,6 +132,7 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix) while (1) { struct pollfd pfd[2]; + ssize_t processed[2] = { 0, 0 }; int status; pfd[0].fd = fd1[0]; @@ -147,12 +149,12 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix) } if (pfd[0].revents & POLLIN) /* Data stream ready */ - process_input(pfd[0].fd, 1); + processed[0] = process_input(pfd[0].fd, 1); if (pfd[1].revents & POLLIN) /* Status stream ready */ - process_input(pfd[1].fd, 2); + processed[1] = process_input(pfd[1].fd, 2); /* Always finish to read data when available */ - if ((pfd[0].revents | pfd[1].revents) & POLLIN) + if (processed[0] || processed[1]) continue; if (waitpid(writer, &status, 0) < 0) From 3eb9699733355d27fd5442492d66ec3c759e0c8b Mon Sep 17 00:00:00 2001 From: Clemens Buchacher Date: Wed, 17 Jun 2009 15:38:36 +0200 Subject: [PATCH 042/211] fetch: do not create ref from empty name Previously, the refspec ":" would be expanded to ":refs/heads/". Instead, treat an empty just like refspecs without a colon. Signed-off-by: Clemens Buchacher Signed-off-by: Junio C Hamano --- remote.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/remote.c b/remote.c index d66e2f3c93..39583d52b9 100644 --- a/remote.c +++ b/remote.c @@ -1254,7 +1254,7 @@ struct ref *get_remote_ref(const struct ref *remote_refs, const char *name) static struct ref *get_local_ref(const char *name) { - if (!name) + if (!name || name[0] == '\0') return NULL; if (!prefixcmp(name, "refs/")) From cb8a9bd518002dd4fb693df6230b4976bafc15e0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Jun 2009 14:31:32 +0200 Subject: [PATCH 043/211] Test cccmd in t9001-send-email.sh and fix some bugs For another patch series I'm working on I needed some tests for the cc-cmd feature of git-send-email. This patch adds 3 tests for the feature and for the possibility to specify --suppress-cc multiple times, and fixes two bugs. The first bug is that the --suppress-cc option for `cccmd' was misspelled as `ccmd' in the code. The second bug, which is actually found only with my other series, is that the argument to the cccmd is never quoted, so the cccmd would fail with patch file names containing a space. A third bug I fix (in the docs) is that the bodycc argument was actually spelled ccbody in the documentation and bash completion. Signed-off-by: Paolo Bonzini Cc: Markus Heidelberg Signed-off-by: Junio C Hamano --- Documentation/git-send-email.txt | 4 +- contrib/completion/git-completion.bash | 2 +- git-send-email.perl | 4 +- t/t9001-send-email.sh | 80 ++++++++++++++++++++++++-- 4 files changed, 80 insertions(+), 10 deletions(-) diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index 9902da43c7..fbde2d3be5 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -193,12 +193,12 @@ Automating - 'self' will avoid including the sender - 'cc' will avoid including anyone mentioned in Cc lines in the patch header except for self (use 'self' for that). -- 'ccbody' will avoid including anyone mentioned in Cc lines in the +- 'bodycc' will avoid including anyone mentioned in Cc lines in the patch body (commit message) except for self (use 'self' for that). - 'sob' will avoid including anyone mentioned in Signed-off-by lines except for self (use 'self' for that). - 'cccmd' will avoid running the --cc-cmd. -- 'body' is equivalent to 'sob' + 'ccbody' +- 'body' is equivalent to 'sob' + 'bodycc' - 'all' will suppress all auto cc values. -- + diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 80ab4e45eb..b60cb68a8b 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -1299,7 +1299,7 @@ _git_rebase () } __git_send_email_confirm_options="always never auto cc compose" -__git_send_email_suppresscc_options="author self cc ccbody sob cccmd body all" +__git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all" _git_send_email () { diff --git a/git-send-email.perl b/git-send-email.perl index 303e03a8ce..8ce6f1fe57 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -334,7 +334,7 @@ if (@suppress_cc) { } if ($suppress_cc{'all'}) { - foreach my $entry (qw (ccmd cc author self sob body bodycc)) { + foreach my $entry (qw (cccmd cc author self sob body bodycc)) { $suppress_cc{$entry} = 1; } delete $suppress_cc{'all'}; @@ -1104,7 +1104,7 @@ foreach my $t (@files) { close F; if (defined $cc_cmd && !$suppress_cc{'cccmd'}) { - open(F, "$cc_cmd $t |") + open(F, "$cc_cmd \Q$t\E |") or die "(cc-cmd) Could not execute '$cc_cmd'"; while() { my $c = $_; diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 9ce04fd472..fb7d9f3e4a 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -148,6 +148,22 @@ test_expect_success 'Prompting works' ' grep "^To: to@example.com$" msgtxt1 ' +test_expect_success 'cccmd works' ' + clean_fake_sendmail && + cp $patches cccmd.patch && + echo cccmd--cccmd@example.com >>cccmd.patch && + echo sed -n s/^cccmd--//p \"\$1\" > cccmd-sed && + chmod +x cccmd-sed && + git send-email \ + --from="Example " \ + --to=nobody@example.com \ + --cc-cmd=./cccmd-sed \ + --smtp-server="$(pwd)/fake.sendmail" \ + cccmd.patch \ + && + grep ^Cc:.*cccmd@example.com msgtxt1 +' + z8=zzzzzzzz z64=$z8$z8$z8$z8$z8$z8$z8$z8 z512=$z64$z64$z64$z64$z64$z64$z64$z64 @@ -274,7 +290,7 @@ EOF test_suppression () { git send-email \ --dry-run \ - --suppress-cc=$1 \ + --suppress-cc=$1 ${2+"--suppress-cc=$2"} \ --from="Example " \ --to=to@example.com \ --smtp-server relay.example.com \ @@ -282,8 +298,8 @@ test_suppression () { sed -e "s/^\(Date:\).*/\1 DATE-STRING/" \ -e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \ -e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \ - >actual-suppress-$1 && - test_cmp expected-suppress-$1 actual-suppress-$1 + >actual-suppress-$1${2+"-$2"} && + test_cmp expected-suppress-$1${2+"-$2"} actual-suppress-$1${2+"-$2"} } test_expect_success 'sendemail.cc set' ' @@ -316,6 +332,34 @@ test_expect_success 'sendemail.cc unset' ' test_suppression sob ' +cat >expected-suppress-cccmd <<\EOF +0001-Second.patch +(mbox) Adding cc: A from line 'From: A ' +(mbox) Adding cc: One from line 'Cc: One , two@example.com' +(mbox) Adding cc: two@example.com from line 'Cc: One , two@example.com' +(body) Adding cc: C O Mitter from line 'Signed-off-by: C O Mitter ' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM: +RCPT TO:,,,, +From: Example +To: to@example.com +Cc: A , One , two@example.com, C O Mitter +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_expect_success 'sendemail.cccmd' ' + echo echo cc-cmd@example.com > cccmd && + chmod +x cccmd && + git config sendemail.cccmd ./cccmd && + test_suppression cccmd +' + cat >expected-suppress-all <<\EOF 0001-Second.patch Dry-OK. Log says: @@ -341,6 +385,31 @@ cat >expected-suppress-body <<\EOF (mbox) Adding cc: A from line 'From: A ' (mbox) Adding cc: One from line 'Cc: One , two@example.com' (mbox) Adding cc: two@example.com from line 'Cc: One , two@example.com' +(cc-cmd) Adding cc: cc-cmd@example.com from: './cccmd' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM: +RCPT TO:,,,, +From: Example +To: to@example.com +Cc: A , One , two@example.com, cc-cmd@example.com +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_expect_success '--suppress-cc=body' ' + test_suppression body +' + +cat >expected-suppress-body-cccmd <<\EOF +0001-Second.patch +(mbox) Adding cc: A from line 'From: A ' +(mbox) Adding cc: One from line 'Cc: One , two@example.com' +(mbox) Adding cc: two@example.com from line 'Cc: One , two@example.com' Dry-OK. Log says: Server: relay.example.com MAIL FROM: @@ -356,8 +425,8 @@ X-Mailer: X-MAILER-STRING Result: OK EOF -test_expect_success '--suppress-cc=body' ' - test_suppression body +test_expect_success '--suppress-cc=body --suppress-cc=cccmd' ' + test_suppression body cccmd ' cat >expected-suppress-sob <<\EOF @@ -381,6 +450,7 @@ Result: OK EOF test_expect_success '--suppress-cc=sob' ' + git config --unset sendemail.cccmd test_suppression sob ' From 02232adfd8bdc692bbe408ead7332ebfe416e83d Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 16 Jun 2009 15:07:40 -0400 Subject: [PATCH 044/211] Makefile: refactor regex compat support There was no tweakable knob to use the regex compat code; it was embedded in the mingw build. Since other platforms may want to use it, let's factor it out in the usual way for build configuration knobs. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 41ab8e9e0d..0cb21da6dd 100644 --- a/Makefile +++ b/Makefile @@ -194,6 +194,8 @@ all:: # # Define USE_NED_ALLOCATOR if you want to replace the platforms default # memory allocators with the nedmalloc allocator written by Niall Douglas. +# +# Define NO_REGEX if you have no or inferior regex support in your C library. GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE @$(SHELL_PATH) ./GIT-VERSION-GEN @@ -884,9 +886,10 @@ ifneq (,$(findstring MINGW,$(uname_S))) USE_NED_ALLOCATOR = YesPlease UNRELIABLE_FSTAT = UnfortunatelyYes OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo - COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch + NO_REGEX = YesPlease + COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\" - COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/regex/regex.o compat/winansi.o + COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o EXTLIBS += -lws2_32 X = .exe ifneq (,$(wildcard ../THIS_IS_MSYSGIT)) @@ -1200,6 +1203,10 @@ endif ifdef UNRELIABLE_FSTAT BASIC_CFLAGS += -DUNRELIABLE_FSTAT endif +ifdef NO_REGEX + COMPAT_CFLAGS += -Icompat/regex + COMPAT_OBJS += compat/regex/regex.o +endif ifdef USE_NED_ALLOCATOR COMPAT_CFLAGS += -DUSE_NED_ALLOCATOR -DOVERRIDE_STRDUP -DNDEBUG -DREPLACE_SYSTEM_ALLOCATOR -Icompat/nedmalloc From ee78cac22b3e5e3f93898361b87a38b488c5592e Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 16 Jun 2009 15:08:21 -0400 Subject: [PATCH 045/211] Makefile: use compat regex on Solaris The system regex is either slow or buggy for complex patterns, like the built-in xfuncname pattern for java files. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 0cb21da6dd..3bd0c08f4b 100644 --- a/Makefile +++ b/Makefile @@ -725,6 +725,7 @@ ifeq ($(uname_S),SunOS) NO_MEMMEM = YesPlease NO_MKDTEMP = YesPlease NO_MKSTEMPS = YesPlease + NO_REGEX = YesPlease ifeq ($(uname_R),5.7) NEEDS_RESOLV = YesPlease NO_IPV6 = YesPlease From 30dd916348001e4313708473d91d633d3b14d1b5 Mon Sep 17 00:00:00 2001 From: Mark Lodato Date: Wed, 27 May 2009 23:16:02 -0400 Subject: [PATCH 046/211] http.c: prompt for SSL client certificate password If an SSL client certificate is enabled (via http.sslcert or GIT_SSL_CERT), prompt for the certificate password rather than defaulting to OpenSSL's password prompt. This causes the prompt to only appear once each run. Previously, OpenSSL prompted the user *many* times, causing git to be unusable over HTTPS with client-side certificates. Note that the password is stored in memory in the clear while the program is running. This may be a security problem if git crashes and core dumps. The user is always prompted, even if the certificate is not encrypted. This should be fine; unencrypted certificates are rare and a security risk anyway. Signed-off-by: Mark Lodato Signed-off-by: Junio C Hamano --- http.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/http.c b/http.c index 2e3d6493ef..1c138135d7 100644 --- a/http.c +++ b/http.c @@ -27,6 +27,17 @@ static int curl_ftp_no_epsv; static const char *curl_http_proxy; static char *user_name, *user_pass; +#if LIBCURL_VERSION_NUM >= 0x071700 +/* Use CURLOPT_KEYPASSWD as is */ +#elif LIBCURL_VERSION_NUM >= 0x070903 +#define CURLOPT_KEYPASSWD CURLOPT_SSLKEYPASSWD +#else +#define CURLOPT_KEYPASSWD CURLOPT_SSLCERTPASSWD +#endif + +static char *ssl_cert_password; +static int ssl_cert_password_required; + static struct curl_slist *pragma_header; static struct active_request_slot *active_queue_head; @@ -167,6 +178,22 @@ static void init_curl_http_auth(CURL *result) } } +static int has_cert_password(void) +{ + if (ssl_cert_password != NULL) + return 1; + if (ssl_cert == NULL || ssl_cert_password_required != 1) + return 0; + /* Only prompt the user once. */ + ssl_cert_password_required = -1; + ssl_cert_password = getpass("Certificate Password: "); + if (ssl_cert_password != NULL) { + ssl_cert_password = xstrdup(ssl_cert_password); + return 1; + } else + return 0; +} + static CURL *get_curl_handle(void) { CURL *result = curl_easy_init(); @@ -189,6 +216,8 @@ static CURL *get_curl_handle(void) if (ssl_cert != NULL) curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert); + if (has_cert_password()) + curl_easy_setopt(result, CURLOPT_KEYPASSWD, ssl_cert_password); #if LIBCURL_VERSION_NUM >= 0x070902 if (ssl_key != NULL) curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key); @@ -329,8 +358,11 @@ void http_init(struct remote *remote) if (getenv("GIT_CURL_FTP_NO_EPSV")) curl_ftp_no_epsv = 1; - if (remote && remote->url && remote->url[0]) + if (remote && remote->url && remote->url[0]) { http_auth_init(remote->url[0]); + if (!prefixcmp(remote->url[0], "https://")) + ssl_cert_password_required = 1; + } #ifndef NO_CURL_EASY_DUPHANDLE curl_default = get_curl_handle(); @@ -370,6 +402,13 @@ void http_cleanup(void) free((void *)curl_http_proxy); curl_http_proxy = NULL; } + + if (ssl_cert_password != NULL) { + memset(ssl_cert_password, 0, strlen(ssl_cert_password)); + free(ssl_cert_password); + ssl_cert_password = NULL; + } + ssl_cert_password_required = 0; } struct active_request_slot *get_active_slot(void) From 754ae192a4390baeb4d00b96e72c69023efb22ee Mon Sep 17 00:00:00 2001 From: Mark Lodato Date: Wed, 27 May 2009 23:16:03 -0400 Subject: [PATCH 047/211] http.c: add http.sslCertPasswordProtected option Add a configuration option, http.sslCertPasswordProtected, and associated environment variable, GIT_SSL_CERT_PASSWORD_PROTECTED, to enable SSL client certificate password prompt from within git. If this option is false and if the environment variable does not exist, git falls back to OpenSSL's prompts (as in earlier versions of git). The environment variable may only be used to enable, not to disable git's password prompt. This behavior mimics GIT_NO_VERIFY; the mere existence of the variable is all that is checked. Signed-off-by: Mark Lodato Signed-off-by: Junio C Hamano --- Documentation/config.txt | 6 ++++++ http.c | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 3a86d1f8f0..2649b303fa 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1043,6 +1043,12 @@ http.sslKey:: over HTTPS. Can be overridden by the 'GIT_SSL_KEY' environment variable. +http.sslCertPasswordProtected:: + Enable git's password prompt for the SSL certificate. Otherwise + OpenSSL will prompt the user, possibly many times, if the + certificate or private key is encrypted. Can be overridden by the + 'GIT_SSL_CERT_PASSWORD_PROTECTED' environment variable. + http.sslCAInfo:: File containing the certificates to verify the peer with when fetching or pushing over HTTPS. Can be overridden by the diff --git a/http.c b/http.c index 1c138135d7..1b140d381d 100644 --- a/http.c +++ b/http.c @@ -140,6 +140,11 @@ static int http_options(const char *var, const char *value, void *cb) #endif if (!strcmp("http.sslcainfo", var)) return git_config_string(&ssl_cainfo, var, value); + if (!strcmp("http.sslcertpasswordprotected", var)) { + if (git_config_bool(var, value)) + ssl_cert_password_required = 1; + return 0; + } #ifdef USE_CURL_MULTI if (!strcmp("http.maxrequests", var)) { max_requests = git_config_int(var, value); @@ -360,7 +365,9 @@ void http_init(struct remote *remote) if (remote && remote->url && remote->url[0]) { http_auth_init(remote->url[0]); - if (!prefixcmp(remote->url[0], "https://")) + if (!ssl_cert_password_required && + getenv("GIT_SSL_CERT_PASSWORD_PROTECTED") && + !prefixcmp(remote->url[0], "https://")) ssl_cert_password_required = 1; } From 5d87dd4fcac808fc0f0b993b470644ba7d2d62a2 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Sun, 14 Jun 2009 22:38:51 +0200 Subject: [PATCH 048/211] daemon: send stderr of service programs to the syslog If git-daemon is run with --detach or --inetd, then stderr is explicitly redirected to /dev/null. But notice that the service programs were spawned via execl_git_cmd(), in particular, the stderr channel is inherited from the daemon. This means that errors that the programs wrote to stderr (for example, via die()), went to /dev/null. This patch arranges that the daemon does not merely exec the service program, but forks it and monitors stderr of the child; it writes the errors that it produces to the daemons log via logerror(). A consequence is that the daemon process remains in memory for the full duration of the service program, but this cannot be avoided. Signed-off-by: Johannes Sixt Signed-off-by: Junio C Hamano --- daemon.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/daemon.c b/daemon.c index b2babcc076..a7834efbab 100644 --- a/daemon.c +++ b/daemon.c @@ -1,6 +1,8 @@ #include "cache.h" #include "pkt-line.h" #include "exec_cmd.h" +#include "run-command.h" +#include "strbuf.h" #include @@ -343,28 +345,66 @@ static int run_service(char *dir, struct daemon_service *service) return service->fn(); } +static void copy_to_log(int fd) +{ + struct strbuf line = STRBUF_INIT; + FILE *fp; + + fp = fdopen(fd, "r"); + if (fp == NULL) { + logerror("fdopen of error channel failed"); + close(fd); + return; + } + + while (strbuf_getline(&line, fp, '\n') != EOF) { + logerror("%s", line.buf); + strbuf_setlen(&line, 0); + } + + strbuf_release(&line); + fclose(fp); +} + +static int run_service_command(const char **argv) +{ + struct child_process cld; + + memset(&cld, 0, sizeof(cld)); + cld.argv = argv; + cld.git_cmd = 1; + cld.err = -1; + if (start_command(&cld)) + return -1; + + close(0); + close(1); + + copy_to_log(cld.err); + + return finish_command(&cld); +} + static int upload_pack(void) { /* Timeout as string */ char timeout_buf[64]; + const char *argv[] = { "upload-pack", "--strict", timeout_buf, ".", NULL }; snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout); - - /* git-upload-pack only ever reads stuff, so this is safe */ - execl_git_cmd("upload-pack", "--strict", timeout_buf, ".", NULL); - return -1; + return run_service_command(argv); } static int upload_archive(void) { - execl_git_cmd("upload-archive", ".", NULL); - return -1; + static const char *argv[] = { "upload-archive", ".", NULL }; + return run_service_command(argv); } static int receive_pack(void) { - execl_git_cmd("receive-pack", ".", NULL); - return -1; + static const char *argv[] = { "receive-pack", ".", NULL }; + return run_service_command(argv); } static struct daemon_service daemon_service[] = { From 9462e3f59cd5a545330a9490a27d68b79f1d0ce7 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Tue, 16 Jun 2009 20:41:16 +0200 Subject: [PATCH 049/211] upload-pack: squelch progress indicator if client cannot see it upload-pack runs pack-objects, which generates progress indicator output on its stderr. If the client requests a sideband, this indicator is sent to the client; but if it did not, then the progress is written to upload-pack's own stderr. If upload-pack is itself run from git-daemon (and if the client did not request a sideband) the progress indicator never reaches the client and it need not be generated in the first place. With this patch the progress indicator is suppressed in this situation. Signed-off-by: Johannes Sixt Signed-off-by: Junio C Hamano --- upload-pack.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/upload-pack.c b/upload-pack.c index edc7861228..841ebb534a 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -28,7 +28,7 @@ static unsigned long oldest_have; static int multi_ack, nr_our_refs; static int use_thin_pack, use_ofs_delta, use_include_tag; -static int no_progress; +static int no_progress, daemon_mode; static struct object_array have_obj; static struct object_array want_obj; static unsigned int timeout; @@ -521,6 +521,10 @@ static void receive_needs(void) } if (debug_fd) write_in_full(debug_fd, "#E\n", 3); + + if (!use_sideband && daemon_mode) + no_progress = 1; + if (depth == 0 && shallows.nr == 0) return; if (depth > 0) { @@ -630,6 +634,7 @@ int main(int argc, char **argv) } if (!prefixcmp(arg, "--timeout=")) { timeout = atoi(arg+10); + daemon_mode = 1; continue; } if (!strcmp(arg, "--")) { From 0e987a12fc1d481d81ad9c56f4714efb08667213 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 16 Jun 2009 15:33:01 -0700 Subject: [PATCH 050/211] am, rebase: teach quiet option git-am and git-rebase are talkative scripts. Teach them to be quiet when told, allowing them to speak only when they fail or experience errors. The quiet option is maintained when git-am or git-rebase fails to apply a patch. This means subsequent --resolved, --continue, --skip, --abort invocations will be quiet if the original invocation was quiet. Drop a handful of >&2 redirection; the rest of the program sends all the info messages to stdout, not to stderr. Signed-off-by: Stephen Boyd Signed-off-by: Junio C Hamano --- Documentation/git-am.txt | 6 ++++- Documentation/git-rebase.txt | 4 +++ git-am.sh | 26 +++++++++++++------ git-rebase.sh | 48 ++++++++++++++++++++++++++++-------- t/t3400-rebase.sh | 19 +++++++++----- t/t4150-am.sh | 18 ++++++++++++++ 6 files changed, 97 insertions(+), 24 deletions(-) diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index 6d92cbee64..32e689b2bf 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -13,7 +13,7 @@ SYNOPSIS [--3way] [--interactive] [--committer-date-is-author-date] [--ignore-date] [--whitespace=