List of commits:
Subject Hash Author Date (UTC)
Fixed the crash with big diffs by setting a limit 788e15942d8272685764a25b640eba2c07046437 Catalin(ux) M. BOIE 2017-04-15 06:24:30
Allow .well-known folder access 90519cd03bf64839d1a9fc2497e58bd63d8ce6f3 Catalin(ux) M. BOIE 2017-04-12 16:50:16
When an un-auth user is visiting a user page with no repo, do not invite to create a repo 6904e1eac3f46c281ae6b4757bcaa16d2acc6169 Catalin(ux) M. BOIE 2017-03-27 15:23:52
Added a 'push' target in Makefile to not forget to push tags... 92a9b78e26d8a3e7b466f5aa45678dd2db8d4310 Catalin(ux) M. BOIE 2017-03-26 14:29:55
Bump version to 0.67 6f1c9a6d7f7d40d65def54e23a3590556a346bb8 Catalin(ux) M. BOIE 2017-03-26 09:44:32
Cosmetic cb68f1921782a503675c592dc7484aa26b8815b6 Catalin(ux) M. BOIE 2017-03-26 09:37:41
Improve state handling: do not check for an old value; verify if table exists before doing a select 17d8eb4b4592dd96e62a8da74d87d3d3b26aeb86 Catalin(ux) M. BOIE 2017-03-26 09:37:01
Impoved debug for cache 4d6349f7143d61583e6d2d9612c89b55af4eea97 Catalin(ux) M. BOIE 2017-03-26 09:36:08
I cannot be sure if the data is stored only in Germany. And we do backups in Romania. 1610c997dbda53c0a21e301b51832d9285ecbcf2 Catalin(ux) M. BOIE 2017-03-26 08:24:46
Removed a not used variable 4d2bab105c6f7748ca53d9a8301a2da320153d53 Catalin(ux) M. BOIE 2017-03-21 20:15:29
tests: ignore some dirs 7260fc44f8d0197b917bc13a0ac19eb8c58d4534 Catalin(ux) M. BOIE 2017-03-21 20:01:03
Link to anon push doc 42dbfdc9ad5fad0157388f239f790f2e8f4de7c2 Catalin(ux) M. BOIE 2017-03-21 20:00:45
comparison: add red/green for css/js sizes and for pagespeed cbcda26a9d20c115eb0931ab2af69f3c2315ab7d Catalin(ux) M. BOIE 2017-03-21 19:44:47
Trim the hints for cloning the tree 59bc91f5229abf96f453d872a58a2c96cf18198c Catalin(ux) M. BOIE 2017-03-21 19:35:58
Do the right thing (no error) when an empty tree is present 7c138f486a81d09df44e811714d7bdeb92d7c01d Catalin(ux) M. BOIE 2017-03-21 19:34:03
Do not use UA when building anti-CSRF token. Think about plugins which change the UA at every request 7346fceeff8bea1eaa500dd3ce1677deb84f8b77 Catalin(ux) M. BOIE 2017-03-21 16:36:46
Do not create a namespace anymore if the user has the rights to push 13f8037ba76b57ae919758609c523dcbb6588745 Catalin(ux) M. BOIE 2017-03-19 19:44:07
Docker improvements c3c0f8ff3f5a2f9acfeea2e9bbf271cfeae4a8bd Catalin(ux) M. BOIE 2017-03-19 19:43:25
Small changes regarding more debugging in several places 03407e5f7562ac997612c56fd20fe067162ea8de Catalin(ux) M. BOIE 2017-03-19 19:42:58
Some improvements for comparison e3a06443fba2c22009f0bde4ea9c3f201a9803cb Catalin(ux) M. BOIE 2017-03-19 19:41:53
Commit 788e15942d8272685764a25b640eba2c07046437 - Fixed the crash with big diffs by setting a limit
Author: Catalin(ux) M. BOIE
Author date (UTC): 2017-04-15 06:24
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2017-04-15 06:24
Parent(s): 90519cd03bf64839d1a9fc2497e58bd63d8ce6f3
Signer:
Signing key:
Signing status: N
Tree: 72d2adced959baabedccb59063c008f27a3ecfc2
File Lines added Lines deleted
inc/git.inc.php 386 122
inc/log.inc.php 1 1
tests/Makefile 1 0
tests/git.php 133 19
tests/git_log1.expected 3 4
tests/git_log1.php 2 1
tests/git_log1.sh 1 1
File inc/git.inc.php changed (mode: 100644) (index f178830..d76ab44)
... ... require_once($INC . "/log.inc.php");
4 4 require_once($INC . "/prof.inc.php"); require_once($INC . "/prof.inc.php");
5 5 require_once($INC . "/events.inc.php"); require_once($INC . "/events.inc.php");
6 6
7 if (!isset($rg_git_patch_limit))
8 $rg_git_patch_limit = 5000;
9
10 $rg_git_debug = 0;
11
7 12 $rg_git_zero = "0000000000000000000000000000000000000000"; $rg_git_zero = "0000000000000000000000000000000000000000";
8 13 $rg_git_empty = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"; $rg_git_empty = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
9 14 define('GIT_LINK_MASK', intval(base_convert('160000', 8, 10))); define('GIT_LINK_MASK', intval(base_convert('160000', 8, 10)));
 
... ... function rg_git_info_pack($band, $msg)
70 75 echo rg_git_pack($s); echo rg_git_pack($s);
71 76 } }
72 77
78 /*
79 * Fix from/to references
80 * Helper for several functions.
81 */
82 function rg_git_from_to($from, $to)
83 {
84 global $rg_git_zero;
85 global $rg_git_empty;
86
87 if (empty($from) && empty($to)) {
88 rg_log('from/to empty');
89 $from_to = '';
90 } else if (empty($from)) {
91 rg_log('from empty');
92 $from_to = $to;
93 } else if (strcmp($from, $rg_git_zero) == 0) {
94 rg_log('from zero');
95 $from_to = $rg_git_empty . '..' . $to;
96 } else {
97 $from_to = $from . '..' . $to;
98 }
99
100 return $from_to;
101 }
102
73 103 /* /*
74 104 * Installs rg hooks instead of original ones, by making a link * Installs rg hooks instead of original ones, by making a link
75 105 */ */
 
... ... function rg_git_ls_tree($repo_path, $tree, $path)
625 655
626 656 /* /*
627 657 * Transforms a diff into an array (ready for rg_git_diff) * Transforms a diff into an array (ready for rg_git_diff)
658 * @out - will be populated with the chunks
628 659 */ */
629 function rg_git_diff2array($diff, &$extra)
660 function rg_git_diff2array($diff, &$out)
630 661 { {
662 global $rg_git_debug;
663
631 664 rg_prof_start("git_diff2array"); rg_prof_start("git_diff2array");
632 665 //rg_log_ml("DEBUG: git_diff2array: diff: " . $diff); //rg_log_ml("DEBUG: git_diff2array: diff: " . $diff);
633 666
634 $ret = array();
635
636 $extra['lines_add'] = 0;
637 $extra['lines_del'] = 0;
638
667 $ret = TRUE;
639 668 $lines = explode("\n", $diff); $lines = explode("\n", $diff);
640 669 //rg_log_ml("DEBUG: lines: " . print_r($lines, TRUE)); //rg_log_ml("DEBUG: lines: " . print_r($lines, TRUE));
641
642 $file = -1;
643 670 foreach ($lines as $line) { foreach ($lines as $line) {
644 //rg_log("DEBUG: line=$line");
671 if ($rg_git_debug > 90)
672 rg_log("DEBUG: line=$line");
645 673
646 674 // format: diff --git a/a b/a // format: diff --git a/a b/a
647 675 if (strncmp($line, "diff --git ", 11) == 0) { if (strncmp($line, "diff --git ", 11) == 0) {
648 $file++;
649 $ret[$file] = array();
650 $ret[$file]['flags'] = "";
651 $ret[$file]['old_mode'] = "";
652 $ret[$file]['mode'] = "";
653 $ret[$file]['similarity'] = "";
654 $ret[$file]['dissimilarity'] = "";
655 $ret[$file]['lines_add'] = 0;
656 $ret[$file]['lines_del'] = 0;
676 $a = array();
677 $a['flags'] = '';
678 $a['old_mode'] = '';
679 $a['mode'] = '';
680 $a['similarity'] = '';
681 $a['dissimilarity'] = '';
657 682
658 683 $rest = substr($line, 11); $rest = substr($line, 11);
659 684 //rg_log("DEBUG: rest=$rest."); //rg_log("DEBUG: rest=$rest.");
 
... ... function rg_git_diff2array($diff, &$extra)
666 691 $_file = substr($_file, 1, -1); $_file = substr($_file, 1, -1);
667 692 $_file = str_replace('\"', '"', $_file); $_file = str_replace('\"', '"', $_file);
668 693 } }
669 $ret[$file]['file_from'] = $_t[0];
670 $ret[$file]['file'] = $_t[1];
671 $ret[$file]['index'] = "";
672 $ret[$file]['chunks'] = array();
694 $a['file_from'] = $_t[0];
695 $a['file'] = $_t[1];
696 $a['index'] = '';
697 $a['chunks'] = array();
698
699 $file = $a['file'];
700 if (!isset($out[$file])) {
701 rg_git_set_error('internal error');
702 rg_internal_error('we have a diff for a non-existing file');
703 $ret = FALSE;
704 break;
705 }
706
707 foreach ($a as $k => $v)
708 $out[$file][$k] = $v;
673 709 continue; continue;
674 710 } }
675 711
676 712 if (strncmp($line, "old mode ", 9) == 0) { if (strncmp($line, "old mode ", 9) == 0) {
677 $ret[$file]['old_mode'] = substr($line, 9);
713 $out[$file]['old_mode'] = substr($line, 9);
678 714 continue; continue;
679 715 } }
680 716
681 717 if (strncmp($line, "new mode ", 9) == 0) { if (strncmp($line, "new mode ", 9) == 0) {
682 $ret[$file]['mode'] = substr($line, 9);
718 $out[$file]['mode'] = substr($line, 9);
683 719 continue; continue;
684 720 } }
685 721
686 722 if (strncmp($line, "deleted file mode ", 18) == 0) { if (strncmp($line, "deleted file mode ", 18) == 0) {
687 $ret[$file]['flags'] .= "D";
688 $ret[$file]['old_mode'] = substr($line, 18);
723 $out[$file]['flags'] .= 'D';
724 $out[$file]['old_mode'] = substr($line, 18);
689 725 continue; continue;
690 726 } }
691 727
692 728 if (strncmp($line, "new file mode ", 14) == 0) { if (strncmp($line, "new file mode ", 14) == 0) {
693 $ret[$file]['flags'] .= "N";
694 $ret[$file]['mode'] = substr($line, 14);
729 $out[$file]['flags'] .= 'N';
730 $out[$file]['mode'] = substr($line, 14);
695 731 continue; continue;
696 732 } }
697 733
698 734 if (strncmp($line, "copy from ", 10) == 0) { if (strncmp($line, "copy from ", 10) == 0) {
699 $ret[$file]['flags'] .= "C";
735 $out[$file]['flags'] .= 'C';
700 736 continue; continue;
701 737 } }
702 738
 
... ... function rg_git_diff2array($diff, &$extra)
704 740 continue; continue;
705 741
706 742 if (strncmp($line, "rename from ", 12) == 0) { if (strncmp($line, "rename from ", 12) == 0) {
707 $ret[$file]['flags'] .= "R";
743 $out[$file]['flags'] .= 'R';
708 744 continue; continue;
709 745 } }
710 746
 
... ... function rg_git_diff2array($diff, &$extra)
712 748 continue; continue;
713 749
714 750 if (strncmp($line, "similarity index ", 17) == 0) { if (strncmp($line, "similarity index ", 17) == 0) {
715 $ret[$file]['similarity'] = substr($line, 17);
751 $out[$file]['similarity'] = substr($line, 17);
716 752 continue; continue;
717 753 } }
718 754
719 755 if (strncmp($line, "dissimilarity index ", 20) == 0) { if (strncmp($line, "dissimilarity index ", 20) == 0) {
720 $ret[$file]['dissimilarity'] = substr($line, 20);
756 $out[$file]['dissimilarity'] = substr($line, 20);
721 757 continue; continue;
722 758 } }
723 759
 
... ... function rg_git_diff2array($diff, &$extra)
728 764 if (strncmp($line, "index ", 6) == 0) { if (strncmp($line, "index ", 6) == 0) {
729 765 $rest = substr($line, 6); $rest = substr($line, 6);
730 766 $_t = explode(' ', $rest); $_t = explode(' ', $rest);
731 $ret[$file]['index'] = $_t[0];
767 $out[$file]['index'] = $_t[0];
732 768 if (isset($_t[1])) if (isset($_t[1]))
733 $ret[$file]['mode'] = $_t[1];
769 $out[$file]['mode'] = $_t[1];
734 770 continue; continue;
735 771 } }
736 772
 
... ... function rg_git_diff2array($diff, &$extra)
748 784 $_t = explode(" ", $line, 5); $_t = explode(" ", $line, 5);
749 785 if (count($_t) < 4) { if (count($_t) < 4) {
750 786 rg_internal_error("invalid line [$line]: count < 4"); rg_internal_error("invalid line [$line]: count < 4");
751 return FALSE;
787 $ret = FALSE;
788 break;
752 789 } }
753 790 $chunk = $_t[1] . " " . $_t[2]; $chunk = $_t[1] . " " . $_t[2];
754 $ret[$file]['chunks'][$chunk] = array();
755 $ret[$file]['chunks'][$chunk]['section'] = isset($_t[4]) ? trim($_t[4]) : "";
791 $out[$file]['chunks'][$chunk] = array();
792 $out[$file]['chunks'][$chunk]['section'] = isset($_t[4]) ? trim($_t[4]) : "";
756 793
757 794 if (strcmp($_t[1], '-1') == 0) { if (strcmp($_t[1], '-1') == 0) {
758 795 $from = '1'; $from = '1';
 
... ... function rg_git_diff2array($diff, &$extra)
760 797 $from = explode(",", substr($_t[1], 1)); /* split '-14,6'; 1: skip '-' prefix */ $from = explode(",", substr($_t[1], 1)); /* split '-14,6'; 1: skip '-' prefix */
761 798 $from = intval($from[0]); $from = intval($from[0]);
762 799 } }
763 $ret[$file]['chunks'][$chunk]['from'] = $from;
800 $out[$file]['chunks'][$chunk]['from'] = $from;
764 801
765 802 if (strcmp($_t[2], '+1') == 0) { if (strcmp($_t[2], '+1') == 0) {
766 803 $to = '1'; $to = '1';
 
... ... function rg_git_diff2array($diff, &$extra)
768 805 $to = explode(",", substr($_t[2], 1)); /* split '+14,8'; 1: skip '+' prefix */ $to = explode(",", substr($_t[2], 1)); /* split '+14,8'; 1: skip '+' prefix */
769 806 $to = intval($to[0]); $to = intval($to[0]);
770 807 } }
771 $ret[$file]['chunks'][$chunk]['to'] = $to;
808 $out[$file]['chunks'][$chunk]['to'] = $to;
772 809 continue; continue;
773 810 } }
774 811
 
... ... function rg_git_diff2array($diff, &$extra)
785 822 if ((strncmp($line, " ", 1) == 0) if ((strncmp($line, " ", 1) == 0)
786 823 || (strncmp($line, "+", 1) == 0) || (strncmp($line, "+", 1) == 0)
787 824 || (strncmp($line, "-", 1) == 0)) { || (strncmp($line, "-", 1) == 0)) {
788 $ret[$file]['chunks'][$chunk]['lines'][] = $line;
789
790 if (strncmp($line, '+', 1) == 0) {
791 $ret[$file]['lines_add']++;
792 $extra['lines_add']++;
793 } else if (strncmp($line, '-', 1) == 0) {
794 $ret[$file]['lines_del']++;
795 $extra['lines_del']++;
796 }
797
825 $out[$file]['chunks'][$chunk]['lines'][] = $line;
798 826 continue; continue;
799 827 } }
800 828
 
... ... function rg_git_diff2array($diff, &$extra)
816 844 /* /*
817 845 * Show last @max commits, no merges, sort by topo * Show last @max commits, no merges, sort by topo
818 846 * @also_patch = TRUE if caller needs also the patch * @also_patch = TRUE if caller needs also the patch
847 * @files - restrict the log to some files; if empty, all are returned.
819 848 * TODO: $also_merges: remove --no-merges * TODO: $also_merges: remove --no-merges
849 * 'simple' because rg_git_log will do the filtering of big diffs.
820 850 */ */
821 function rg_git_log($path, $max, $from, $to, $also_patch)
851 function rg_git_log_simple($repo_path, $max, $from, $to, $also_patch, $files)
822 852 { {
823 global $rg_git_empty, $rg_git_zero;
853 global $rg_git_debug;
854 global $rg_git_patch_limit;
824 855
825 rg_prof_start("git_log");
826 rg_log_enter("git_log: path=$path from=$from to=$to max=$max");
856 rg_prof_start('git_log_simple');
857 rg_log_enter('git_log_simple: repo_path=' . $repo_path
858 . ' max=' . $max . ' from=' . $from . ' to=' . $to
859 . ' also_patch=' . ($also_patch ? 'true' : 'false')
860 . ' files:' . rg_array2string($files));
827 861
828 862 $ret = FALSE; $ret = FALSE;
829 863 while (1) { while (1) {
830 $test_for_master = TRUE;
831
832 if (empty($from) && empty($to)) {
833 rg_log('from/to empty');
834 $from_to = '';
835 } else if (empty($from)) {
836 rg_log('from empty');
837 $from_to = $to;
838 } else if (strcmp($from, $rg_git_zero) == 0) {
839 rg_log('from zero');
840 $from_to = $rg_git_empty . '..' . $to;
841 $test_for_master = FALSE;
842 } else {
843 $from_to = $from . '..' . $to;
844 }
845
846 if ($test_for_master) {
847 if (!file_exists($path . "/refs/heads/master")) {
848 if (!file_exists($path . "/.git/refs/heads/master")) {
849 rg_log("Repo is empty.");
850 $ret = array();
851 break;
852 }
864 if (!file_exists($repo_path . '/refs/heads/master')) {
865 if (!file_exists($repo_path . '/.git/refs/heads/master')) {
866 rg_log('Repo is empty.');
867 $ret = array();
868 break;
853 869 } }
854 870 } }
855 871
856 872 $max_count = ($max == 0) ? "" : " --max-count=$max"; $max_count = ($max == 0) ? "" : " --max-count=$max";
857 $patches = $also_patch ? " --patch" : " --shortstat";
873 $patches = $also_patch ? " --patch" : "";
874 $from_to = rg_git_from_to($from, $to);
875 $id = rg_id(16);
876 $sep_start = '-=ROCKETGIT-START-' . $id . '=-';
877 $sep_end = '-=ROCKETGIT_END_OF_VARS-' . $id . '=-';
858 878
859 879 $cmd = "git --no-pager" $cmd = "git --no-pager"
860 . " --git-dir=" . escapeshellarg($path)
880 . " --git-dir=" . escapeshellarg($repo_path)
861 881 . " log" . " log"
862 882 . " --find-copies" . " --find-copies"
883 . " --find-renames"
884 . ' --find-copies-harder'
863 885 . " --no-merges" . " --no-merges"
886 . ' --numstat'
864 887 . " -z" . " -z"
865 888 . $max_count . $max_count
866 889 . $patches . $patches
867 890 . " --pretty=\"format:" . " --pretty=\"format:"
868 . "%x00-=ROCKETGIT=-%x00"
891 . $sep_start
869 892 . "sha1:%H%x00\"\"" . "sha1:%H%x00\"\""
870 893 . "sha1_short:%h%x00\"\"" . "sha1_short:%h%x00\"\""
871 894 . "tree:%T%x00\"\"" . "tree:%T%x00\"\""
 
... ... function rg_git_log($path, $max, $from, $to, $also_patch)
884 907 . "subject:%s%x00\"\"" . "subject:%s%x00\"\""
885 908 . "body:%b%x00\"\"" . "body:%b%x00\"\""
886 909 . "notes:%N%x00\"\"" . "notes:%N%x00\"\""
887 . "%x00ROCKETGIT_END_OF_VARS%x00\"";
910 . $sep_end
911 . "\"";
888 912 if (!empty($from_to)) if (!empty($from_to))
889 913 $cmd .= ' ' . escapeshellarg($from_to); $cmd .= ' ' . escapeshellarg($from_to);
914 if (!empty($files)) {
915 $cmd .= ' --';
916 foreach ($files as $f)
917 $cmd .= ' ' . escapeshellarg($f);
918 }
890 919 $a = rg_exec($cmd, '', FALSE, FALSE); $a = rg_exec($cmd, '', FALSE, FALSE);
891 920 if ($a['ok'] != 1) { if ($a['ok'] != 1) {
892 921 rg_internal_error("error on log (" . $a['errmsg'] . ")"); rg_internal_error("error on log (" . $a['errmsg'] . ")");
 
... ... function rg_git_log($path, $max, $from, $to, $also_patch)
894 923 break; break;
895 924 } }
896 925
897 //rg_log_ml("DEBUG: OUTPUT OF GIT LOG: " . $a['data']);
926 if ($rg_git_debug > 70)
927 rg_log_ml("DEBUG: OUTPUT OF GIT LOG: " . $a['data']);
928
929 // because data starts with the separator, we remove it
930 $blocks = explode($sep_start, $a['data']);
931 unset($blocks[0]);
898 932
899 // because data starts with -=ROCK..., we remove it
900 $a['data'] = substr($a['data'], 14);
901 $blocks = explode("\0-=ROCKETGIT=-\0", "\0" . $a['data']);
933 //rg_log_ml('DEBUG: blocks: ' . print_r($blocks, TRUE));
902 934
903 935 $ret = array(); $ret = array();
904 936 foreach ($blocks as $junk => $block) { foreach ($blocks as $junk => $block) {
 
... ... function rg_git_log($path, $max, $from, $to, $also_patch)
908 940 $y['vars']['commit_url'] = ""; $y['vars']['commit_url'] = "";
909 941
910 942 // split block in two: vars and patches // split block in two: vars and patches
911 $parts = explode("\0ROCKETGIT_END_OF_VARS\0", $block, 2);
943 $parts = explode($sep_end, $block, 2);
944 //rg_log_ml('DEBUG: parts: ' . print_r($parts, TRUE));
912 945
913 946 // vars // vars
914 947 $y['vars']['lines_add'] = 0; $y['vars']['lines_add'] = 0;
915 948 $y['vars']['lines_del'] = 0; $y['vars']['lines_del'] = 0;
916 $x = explode ("\0", trim($parts[0]));
917 $count = count($x);
918 for ($i = 0; $i < $count - 1; $i++) {
919 $_t = explode(":", $x[$i], 2);
949 $x = explode ("\0", $parts[0]);
950 $count = count($x) - 1; // last is empty
951 for ($i = 0; $i < $count; $i++) {
952 $_t = explode(':', $x[$i], 2);
920 953 if (isset($_t[1])) { if (isset($_t[1])) {
921 $y['vars'][$_t[0]] = trim($_t[1]);
954 $y['vars'][$_t[0]] = $_t[1];
922 955 } else if (empty($_t[0])) { } else if (empty($_t[0])) {
923 956 // do nothing // do nothing
924 957 } else { } else {
925 958 //rg_log("DEBUG: Var [" . $_t[0] . "] has no value!"); //rg_log("DEBUG: Var [" . $_t[0] . "] has no value!");
926 959 } }
927 960 } }
961 // Some additions
962 $y['vars']['author date UTC'] = gmdate("Y-m-d H:i:s", $y['vars']['author date']);
963 $y['vars']['committer date UTC'] = gmdate("Y-m-d H:i:s", $y['vars']['committer date']);
928 964
929 965 if (!isset($parts[1])) { if (!isset($parts[1])) {
930 966 // we do nothing // we do nothing
931 } else if ($also_patch) {
932 // patches
933 $y['files'] = rg_git_diff2array($parts[1], $_extra);
934 if ($y['files'] === FALSE)
967 $ret[] = $y;
968 continue;
969 }
970
971 //rg_log_ml('DEBUG parts[1]: ' . print_r($parts[1], TRUE));
972 // numstat [+ diff separated by \0\0]
973 $n_d = explode("\0\0", $parts[1]);
974 //rg_log_ml('DEBUG: n_d: ' . print_r($n_d, TRUE));
975
976 // numstat
977 $numstat = explode("\0", trim($n_d[0]));
978 //rg_log_ml('DEBUG: numstat: ' . print_r($numstat, TRUE));
979 $tc = count($numstat);
980 while ($tc > 0) {
981 $a = explode("\t", array_shift($numstat)); $tc--;
982 //rg_log_ml('DEBUG: a: ' . print_r($a, TRUE));
983
984 // We may have an empty commit
985 if (count($a) == 1)
935 986 break; break;
936 987
937 $y['vars']['lines_add'] = $_extra['lines_add'];
938 $y['vars']['lines_del'] = $_extra['lines_del'];
939 } else {
940 // shortstat
941 //rg_log('DEBUG parts[1]: ' . print_r($parts[1], TRUE));
942 $t = explode(',', $parts[1]);
988 if (count($a) != 3) {
989 rg_internal_error('invalid numstat: c=' . count($a)
990 . ' numstat: ' . print_r($n_d[0], TRUE) . '.');
991 break;
992 }
943 993
944 for ($i = 1; $i < 3; $i++) {
945 if (!isset($t[$i]))
994 $f = $a[2];
995 if (empty($f)) { // it is a rename or copy
996 if ($tc < 2) {
997 rg_internal_error('a rename or copy with invalid fields');
998 rg_internal_error('numstat: '
999 . print_r($n_d[0], TRUE));
946 1000 break; break;
1001 }
947 1002
948 $x = trim($t[$i]);
949 //rg_log('DEBUG: x=[' . $x . ']');
950 if (strstr($x, 'insert'))
951 $y['vars']['lines_add'] += intval($x);
952 else if (strstr($x, 'deletion'))
953 $y['vars']['lines_del'] += intval($x);
954 else
955 rg_log('BUG: unknown field: ' . $x);
1003 // throw away the source (not needed)
1004 array_shift($numstat);
1005 $f = array_shift($numstat);
1006 $tc -= 2;
956 1007 } }
957 1008
958 //rg_log('DEBUG lines_add=' . $y['vars']['lines_add']);
959 //rg_log('DEBUG lines_del=' . $y['vars']['lines_del']);
1009 $y['files'][$f] = array(
1010 'file' => $f,
1011 'chunks' => array(),
1012 'flags' => '',
1013 'lines_add' => intval($a[0]),
1014 'lines_del' => intval($a[1])
1015 );
1016 $y['files'][$f]['changes'] =
1017 $y['files'][$f]['lines_add']
1018 + $y['files'][$f]['lines_del'];
1019
1020 // We will mark over sized diffs for later use
1021 $changes = $y['files'][$f]['lines_add']
1022 + $y['files'][$f]['lines_del'];
1023 //rg_log('DEBUG: File [' . $f . '] '
1024 // . $changes . ' changes');
1025 $y['files'][$f]['oversize_diff'] =
1026 $changes > $rg_git_patch_limit ? 1 : 0;
1027
1028 // Add to total
1029 $y['vars']['lines_add'] += $y['files'][$f]['lines_add'];
1030 $y['vars']['lines_del'] += $y['files'][$f]['lines_del'];
960 1031 } }
1032 //rg_log_ml('DEBUG: files: ' . print_r($y['files'], TRUE));
961 1033
962 // final additions
963 $y['vars']['author date UTC'] = gmdate("Y-m-d H:i:s", $y['vars']['author date']);
964 $y['vars']['committer date UTC'] = gmdate("Y-m-d H:i:s", $y['vars']['committer date']);
1034 if ($also_patch === FALSE) {
1035 $ret[] = $y;
1036 continue;
1037 }
1038
1039 if (!isset($n_d[1])) {
1040 // TODO: can happen if the diff is empty?
1041 rg_internal_error('patch, but diff missing!');
1042 rg_git_set_error('internal error');
1043 $ret = FALSE;
1044 break;
1045 }
1046
1047 // now, patch, if present
1048 if ($rg_git_debug > 80)
1049 rg_log_ml('DEBUG: n_d[1]:' . "\n"
1050 . print_r($n_d[1], TRUE));
1051
1052 $r = rg_git_diff2array($n_d[1], $y['files']);
1053 if ($r === FALSE)
1054 break;
965 1055
1056 //rg_log_ml('DEBUG: diff2array: ' . print_r($y['files'], TRUE));
1057
1058 //rg_log_ml('DEBUG: y: ' . print_r($y, TRUE));
966 1059 $ret[] = $y; $ret[] = $y;
967 1060 } }
968 1061 break; break;
969 1062 } }
970 1063
1064 //rg_log_ml('DEBUG: simple: ' . print_r($ret, TRUE));
1065
1066 rg_log_exit();
1067 rg_prof_end('git_log_simple');
1068 return $ret;
1069 }
1070
1071 /*
1072 * Works on git_log (without patch) output and detect big diffs.
1073 * Returns an array with all the info needed to prepage a 'git log'.
1074 * Will return an empty array if normal log should be called.
1075 */
1076 function rg_git_log_detect_big_diff($stat, $from)
1077 {
1078 rg_log_enter('git_log_detect_big_diff');
1079
1080 rg_log_ml('DEBUG: stat: ' . print_r($stat, TRUE));
1081
1082 $ret = array();
1083 $pos = 0;
1084 $last_was_good = 2; // 2 = not good or bad
1085 $ret[0] = array('from' => $from);
1086
1087 $at_least_one_bad = FALSE;
1088 foreach ($stat as $junk => $per_commit) {
1089 $hash = $per_commit['vars']['sha1'];
1090
1091 $good_files = array();
1092 $we_have_bad_files = FALSE;
1093 foreach ($per_commit['files'] as $fname => $i) {
1094 if ($i['oversize_diff']) {
1095 $we_have_bad_files = TRUE;
1096 $at_least_one_bad = TRUE;
1097 } else {
1098 $good_files[] = $fname;
1099 }
1100 }
1101 if ($we_have_bad_files === FALSE)
1102 $good_files = array(); // = all
1103
1104 //rg_log_enter('DEBUG: hash ' . $hash);
1105 //rg_log('DEBUG: we_have_bad_files='
1106 // . ($we_have_bad_files ? 'TRUE' : 'FALSE'));
1107 //rg_log('DEBUG: last_was_good=' . $last_was_good);
1108 //rg_log_ml('DEBUG: good_files: ' . print_r($good_files, TRUE));
1109
1110 if ($we_have_bad_files) {
1111 if ($last_was_good < 2) {
1112 rg_log('last_was_good == 0/1');
1113 $ret[$pos]['from'] = $hash;
1114 $ret[$pos]['from_to'] = rg_git_from_to($ret[$pos]['from'], $ret[$pos]['to']);
1115 $pos++;
1116 }
1117
1118 $ret[$pos] = array(
1119 'type' => 'bad',
1120 'from' => '', // we do not need it
1121 'to' => $hash,
1122 'good_files' => $good_files
1123 );
1124 $ret[$pos]['from_to'] = rg_git_from_to($ret[$pos]['from'], $ret[$pos]['to']);
1125 $last_was_good = 0;
1126 } else {
1127 // we have no bad files
1128 if ($last_was_good == 1) {
1129 rg_log('last_was_good == 1; do nothing');
1130 } else {
1131 if ($last_was_good == 0) {
1132 rg_log('last_was_good == 0');
1133 $ret[$pos]['from'] = $hash;
1134 $ret[$pos]['from_to'] = rg_git_from_to($ret[$pos]['from'], $ret[$pos]['to']);
1135 $pos++;
1136 } else {
1137 rg_log('last_was_good == 2');
1138 }
1139
1140 $ret[$pos]['type'] = 'good';
1141 $ret[$pos]['to'] = $hash;
1142 }
1143 $last_was_good = 1;
1144 }
1145 //rg_log_exit();
1146 }
1147
1148 // We may not had the chance to set 'from'
1149 if (!isset($ret[$pos]['from'])) {
1150 $ret[$pos]['from'] = $from;
1151 $ret[$pos]['from_to'] = rg_git_from_to($ret[$pos]['from'], $ret[$pos]['to']);
1152 }
1153 //rg_log_ml('DEBUG final (after detect big diff): ' . print_r($ret, TRUE));
1154
1155 // No need to parse the array
1156 if ($at_least_one_bad === FALSE)
1157 $ret = array();
1158
1159 rg_log_exit();
1160 return $ret;
1161 }
1162
1163 /*
1164 * Show last @max commits, no merges, sort by topo
1165 * @also_patch = TRUE if caller needs also the diff
1166 * TODO: $also_merges: remove --no-merges
1167 * '@from' - it will be excluded from the list of commits
1168 */
1169 function rg_git_log($repo_path, $max, $from, $to, $also_patch)
1170 {
1171 rg_prof_start('git_log');
1172 rg_log_enter('git_log: repo_path=' . $repo_path . ' from=' . $from
1173 . ' to=' . $to .' max=' . $max);
1174
1175 $ret = FALSE;
1176 while (1) {
1177 $good_files = array(); // = all
1178 $stat = rg_git_log_simple($repo_path, $max, $from, $to,
1179 FALSE /*also_patch*/, $good_files);
1180
1181 // First, if 'also_path' is FALSE, we just call simple version
1182 // because we do not show a diff which should be filtered.
1183 if ($also_patch === FALSE) {
1184 $ret = $stat;
1185 break;
1186 }
1187
1188 $r = rg_git_log_detect_big_diff($stat, $from);
1189 if (empty($r)) { // = no big diff
1190 $good_files = array(); // = all
1191 $ret = rg_git_log_simple($repo_path, $max, $from, $to,
1192 $also_patch, $good_files);
1193 break;
1194 }
1195
1196 foreach ($r as $i) {
1197 //rg_log_ml('DEBUG: Generating log for ' . print_r($i, TRUE));
1198
1199 if (strcmp($i['type'], 'good') == 0)
1200 $_files = array();
1201 else
1202 $_files = $i['good_files'];
1203
1204 $x = rg_git_log_simple($repo_path, 0 /*max*/,
1205 $i['from'], $i['to'], $also_patch, $_files);
1206 if ($x === FALSE)
1207 break;
1208 //rg_log_ml('DEBUG: x: ' . print_r($x, TRUE));
1209
1210 // Overwrite $stat with the latest info
1211 foreach ($x as $hash => $per_hash) {
1212 foreach ($per_hash['files'] as $f => $per_file)
1213 $stat[$hash]['files'][$f] = $per_file;
1214 }
1215 unset($x);
1216
1217 // TODO: sort files
1218 }
1219
1220 /*
1221 // TODO: now, seems ok, but we need a functinal test
1222 // with more combinations:
1223 // We have: GGBBBBG
1224 // We need B...G...B and others
1225 */
1226 $ret = $stat;
1227 break;
1228 }
1229
1230 rg_log_ml('FINAL: ' . print_r($ret, TRUE));
1231
971 1232 rg_log_exit(); rg_log_exit();
972 rg_prof_end("git_log");
1233 rg_prof_end('git_log');
973 1234 return $ret; return $ret;
974 1235 } }
975 1236
 
... ... function rg_git_diff($id, $a, $template_file)
1111 1372
1112 1373 $ret .= "<table class=\"chunk\">\n"; $ret .= "<table class=\"chunk\">\n";
1113 1374 $ret .= "<tr style=\"border: 1px; background: #dddddd\"><td colspan=\"4\">"; $ret .= "<tr style=\"border: 1px; background: #dddddd\"><td colspan=\"4\">";
1114 if (strstr($finfo['flags'], "N"))
1375 if ($finfo['oversize_diff'] == 1)
1376 $ret .= rg_template('repo/diff_too_big.html',
1377 $finfo, TRUE /*xss*/);
1378 else if (strstr($finfo['flags'], "N"))
1115 1379 $ret .= "File <b>$f</b> added"; $ret .= "File <b>$f</b> added";
1116 1380 else if (strstr($finfo['flags'], "D")) else if (strstr($finfo['flags'], "D"))
1117 1381 $ret .= "File <b>$f</b> deleted"; $ret .= "File <b>$f</b> deleted";
1118 1382 else if (strstr($finfo['flags'], "C")) else if (strstr($finfo['flags'], "C"))
1119 $ret .= "File <b>$f</b> copied from "
1120 . rg_xss_safe($finfo['file_from']);
1383 $ret .= 'File <b>' . $f . '</b> copied from file '
1384 . '<b>' . rg_xss_safe($finfo['file_from']) . '</b>';
1121 1385 else if (strstr($finfo['flags'], "R")) else if (strstr($finfo['flags'], "R"))
1122 $ret .= "File <b>$f</b> renamed from "
1123 . rg_xss_safe($finfo['file_from']);
1386 $ret .= 'File <b>' . $f . '</b> renamed from '
1387 . '<b>' . rg_xss_safe($finfo['file_from']) . '</b>';
1124 1388 else else
1125 1389 $ret .= "File <b>$f</b> changed"; $ret .= "File <b>$f</b> changed";
1126 1390
 
... ... function rg_git_content_by_file($treeish, $file)
1714 1978 /* /*
1715 1979 * High level function that shows commits between two points * High level function that shows commits between two points
1716 1980 * Input is the array returned by rg_git_log() * Input is the array returned by rg_git_log()
1717 * @commit_table - TRUE if you want commit table to show (FALSE for log/commit
1981 * @commit_table - TRUE if you want commit table to show (FALSE for log/commit)
1718 1982 */ */
1719 1983 function rg_git_log2listing($log, $rg, $commit_table) function rg_git_log2listing($log, $rg, $commit_table)
1720 1984 { {
File inc/log.inc.php changed (mode: 100644) (index e77200c..35d0dbb)
... ... function rg_log_ml_enter($a)
231 231 { {
232 232 global $rg_log_level; global $rg_log_level;
233 233
234 $rg_log_level++;
235 234 rg_log_ml($a); rg_log_ml($a);
235 $rg_log_level++;
236 236 } }
237 237
238 238 function rg_log_exit() function rg_log_exit()
File tests/Makefile changed (mode: 100644) (index eead868..6a49202)
... ... all: clean run
6 6
7 7 .PHONY: run .PHONY: run
8 8 run: run:
9 @mkdir -p temp_repos
9 10 @./_run_tests.sh @./_run_tests.sh
10 11
11 12 .PHONY: clean .PHONY: clean
File tests/git.php changed (mode: 100644) (index d8f39cd..eefbc95)
... ... rg_log_set_file("git.log");
12 12 $rg_no_db = TRUE; $rg_no_db = TRUE;
13 13 require_once("common.php"); require_once("common.php");
14 14
15 $rg_git_debug = 100;
15 16
16 17 rg_log(''); rg_log('');
17 18 rg_log("Testing rg_git_log with a rename"); rg_log("Testing rg_git_log with a rename");
18 system("git init git_rename; cd git_rename;"
19 . " touch a; git add a; git commit -a -m \"aaa\";"
20 . " git mv a b; git commit -a -m \"bbb\"");
21 $r = rg_git_log('git_rename/.git', 1, '', '', TRUE);
22 // we do not test here nothing, we will let err- files "speak"
23 system("rm -rf git_rename");
19 $r = rg_exec('rm -rf temp_repos/git_rename'
20 . ' && mkdir temp_repos/git_rename'
21 . ' && cd temp_repos/git_rename'
22 . ' && git init'
23 . ' && seq 0 1000 > a'
24 . ' && echo yyy > b; git add a b; git commit -a -m "aaa"'
25 . ' && cp a aclone; git add aclone'
26 . ' && git mv b b2'
27 . ' && git commit -a -m "bbb"',
28 '', FALSE, FALSE);
29 if ($r['ok'] != 1) {
30 rg_log('Could not exec repo script: ' . $r['errmsg'] . '!');
31 exit(1);
32 }
33 $r = rg_git_log('temp_repos/git_rename/.git', 1, '', '', TRUE);
34 if (@strcmp($r[0]['files']['aclone']['file_from'], 'a') != 0) {
35 rg_log_ml(print_r($r, TRUE));
36 rg_log('git_bin: r[0][files][aclone][file_from] is not "a"!');
37 exit(1);
38 }
39 if (@$r[0]['files']['aclone']['lines_add'] != 0) {
40 rg_log_ml(print_r($r, TRUE));
41 rg_log('git_bin: r[0][files][aclone][lines_add] is not 0!');
42 exit(1);
43 }
44 if (@!strstr($r[0]['files']['aclone']['flags'], 'C')) {
45 rg_log_ml(print_r($r, TRUE));
46 rg_log('git_bin: r[0][files][aclone][flags] does not containc "C"!');
47 exit(1);
48 }
49 if (@strcmp($r[0]['files']['b2']['file_from'], 'b') != 0) {
50 rg_log_ml(print_r($r, TRUE));
51 rg_log('git_bin: r[0][files][b2][file_from] is not "b"!');
52 exit(1);
53 }
54 if (@$r[0]['files']['b2']['lines_add'] != 0) {
55 rg_log_ml(print_r($r, TRUE));
56 rg_log('git_bin: r[0][files][b2][lines_add] is not 0!');
57 exit(1);
58 }
59 if (@!strstr($r[0]['files']['b2']['flags'], 'R')) {
60 rg_log_ml(print_r($r, TRUE));
61 rg_log('git_bin: r[0][files][b2][flags] does not containc "C"!');
62 exit(1);
63 }
64 system("rm -rf temp_repos/git_rename");
24 65
25 66
26 67 rg_log(''); rg_log('');
27 68 rg_log("Testing rg_git_log for binary files"); rg_log("Testing rg_git_log for binary files");
28 system("git init git_bin; cd git_bin;"
29 . " echo -e \x01\x02 > a; git add a; git commit -a -m \"aaa\";"
30 . " echo -e \x01\x03 > a; git commit -a -m \"bbb\"");
31 $r = rg_git_log('git_bin/.git', 0, '', '', FALSE);
32 if ($r[0]['vars']['lines_add'] != 1) {
33 rg_log_ml(print_r($r[0], TRUE));
34 rg_log('git_bin: lines_add is incorrect');
69 $r = rg_exec('rm -rf temp_repos/git_bin'
70 . ' && mkdir temp_repos/git_bin'
71 . ' && cd temp_repos/git_bin'
72 . ' && git init'
73 . ' && seq 0 100 | while read a; do echo -en "\x`printf "%02x" ${a}`"; done > a'
74 . ' && git add a; git commit -a -m "aaa"'
75 . ' && echo -e \x0ff\x03\x90 > a; git commit -a -m "bbb"',
76 '', FALSE, FALSE);
77 if ($r['ok'] != 1) {
78 rg_log('Could not exec repo script: ' . $r['errmsg'] . '!');
79 exit(1);
80 }
81 $r = rg_git_log('temp_repos/git_bin/.git', 0, '', '', TRUE);
82 if (@$r[0]['vars']['lines_add'] != 0) {
83 rg_log_ml(print_r($r, TRUE));
84 rg_log('git_bin: r[0][vars][lines_add] is not 0!');
35 85 exit(1); exit(1);
36 86 } }
37 if ($r[0]['vars']['lines_del'] != 1) {
38 rg_log_ml(print_r($r[0], TRUE));
39 rg_log('git_bin: lines_del is incorrect');
87 if (@$r[0]['vars']['lines_del'] != 0) {
88 rg_log_ml(print_r($r, TRUE));
89 rg_log('git_bin: r[0][vars][lines_del] is not 0!');
40 90 exit(1); exit(1);
41 91 } }
42 system("rm -rf git_bin");
92 if (@strcmp($r[0]['files']['a']['mode'], '100644') != 0) {
93 rg_log_ml(print_r($r, TRUE));
94 rg_log('git_bin: r[0][files][a][mode] is not 100644!');
95 exit(1);
96 }
97 system("rm -rf temp_repos/git_bin");
43 98
44 99
45 100 rg_log(''); rg_log('');
 
... ... system("cd git.tmp; git commit -a -m \"aa\"; git checkout -n b1");
79 134
80 135 rg_log("[*] Testing rg_git_refs..."); rg_log("[*] Testing rg_git_refs...");
81 136 $refs = rg_git_refs("git.tmp"); $refs = rg_git_refs("git.tmp");
82 print_r($refs);
137 //TODO print_r($refs);
83 138
84 139 system("rm -rf git.tmp"); system("rm -rf git.tmp");
85 140
86 141
87 rg_log("OK");
142 rg_log('');
143 rg_log_enter('Testing rg_git_log with a big diff...');
144 $rg_git_patch_limit = 5;
145 $r = rg_exec('mkdir -p temp_repos && cd temp_repos'
146 . ' && rm -rf git_big_diff && mkdir git_big_diff && cd git_big_diff'
147 . ' && git init'
148 . ' && echo -e "line1\nline2\nline3" > a'
149 . ' && echo -e "aaaa" > b'
150 . ' && git add a b'
151 . ' && git commit -a -m "aaa"'
152 . ' && echo -e "\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx" > a'
153 . ' && echo -e "bbbb" > b'
154 . ' && git commit -a -m "bbb"'
155 . ' && echo -e "c" > a'
156 . ' && echo -e "cccc" > b'
157 . ' && git commit -a -m "ccc"'
158 . ' && echo -e "\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx" > a'
159 . ' && echo -e "dddd" > b'
160 . ' && git commit -a -m "ddd"'
161 . ' && echo -e "e" > a'
162 . ' && echo -e "eeee" > b'
163 . ' && git commit -a -m "eee"'
164 . ' && echo -e "f" > a'
165 . ' && echo -e "ffff" > b'
166 . ' && git commit -a -m "fff"'
167 . ' && echo -e "g" > a'
168 . ' && echo -e "gggg" > b'
169 . ' && git commit -a -m "ggg"',
170 '', FALSE, FALSE);
171 if ($r['ok'] != 1) {
172 rg_log('Could not exec repo script: ' . $r['errmsg'] . '!');
173 exit(1);
174 }
175 $r = rg_git_log('temp_repos/git_big_diff/.git', 0, '', '', TRUE);
176 if (@$r[2]['vars']['lines_add'] != 2) {
177 rg_log_ml(print_r($r, TRUE));
178 rg_log('git_bin: lines_add is incorrect');
179 exit(1);
180 }
181 if (@$r[2]['files']['a']['oversize_diff'] != 1) {
182 rg_log_ml(print_r($r, TRUE));
183 rg_log('git_bin: r[2][files][a][oversize_diff] is not 1!');
184 exit(1);
185 }
186 if (!empty($r[2]['files']['a']['chunks'])) {
187 rg_log_ml(print_r($r, TRUE));
188 rg_log('git_bin: r[2][files][a][chunks] is not empty!');
189 exit(1);
190 }
191 if (empty($r[1]['files']['b']['chunks'])) {
192 rg_log_ml(print_r($r, TRUE));
193 rg_log('git_bin: r[1][files][b][chunks] is empty!');
194 exit(1);
195 }
196 system('rm -rf temp_repos/git_big_diff');
197
198
199 // TODO: test with one good/bad commit and with an empty one
200
201 rg_log('OK!');
88 202 ?> ?>
File tests/git_log1.expected changed (mode: 100644) (index 26bef72..9e564c8)
37 37 <br /> <br />
38 38 <a name="file-uniq-id-a3"></a> <a name="file-uniq-id-a3"></a>
39 39 <table class="chunk"> <table class="chunk">
40 <tr style="border: 1px; background: #dddddd"><td colspan="4">File <b>a3</b> renamed from a2 (similarity 100%):</td></tr>
40 <tr style="border: 1px; background: #dddddd"><td colspan="4">File <b>a3</b> renamed from <b>a2</b> (similarity 100%):</td></tr>
41 41 </table> </table>
42 42 <br /> <br />
43 43 <a name="file-uniq-id-c"></a> <a name="file-uniq-id-c"></a>
 
50 50 <br /> <br />
51 51 <a name="file-uniq-id-a2"></a> <a name="file-uniq-id-a2"></a>
52 52 <table class="chunk"> <table class="chunk">
53 <tr style="border: 1px; background: #dddddd"><td colspan="4">File <b>a2</b> added (mode: 100644) (index 0000000..193814c):</td></tr>
54 1 cl-e cl-g aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
53 <tr style="border: 1px; background: #dddddd"><td colspan="4">File <b>a2</b> copied from file <b>a</b> (similarity 100%):</td></tr>
55 54 </table> </table>
56 55 </div> </div>
57 56 <div class="diff"> <div class="diff">
58 57 <br /> <br />
59 58 <a name="file-uniq-id-empty.txt"></a> <a name="file-uniq-id-empty.txt"></a>
60 59 <table class="chunk"> <table class="chunk">
61 <tr style="border: 1px; background: #dddddd"><td colspan="4">File <b>empty.txt</b> added (mode: 100644) (index 0000000..e69de29):</td></tr>
60 <tr style="border: 1px; background: #dddddd"><td colspan="4">File <b>empty.txt</b> copied from file <b>xx&quot;yy&quot;</b> (similarity 100%):</td></tr>
62 61 </table> </table>
63 62 </div> </div>
64 63 <div class="diff"> <div class="diff">
File tests/git_log1.php changed (mode: 100644) (index 4e19e73..c93752a)
... ... if ($r === FALSE) {
25 25 rg_log("Cannot generate log (" . rg_git_error() . ")!"); rg_log("Cannot generate log (" . rg_git_error() . ")!");
26 26 exit(1); exit(1);
27 27 } }
28 file_put_contents(dirname(__FILE__) . "/git_log1.out", print_r($r, TRUE));
29 28
30 29 $final = ''; $final = '';
31 30 foreach ($r as $commit_index => $commit_info) { foreach ($r as $commit_index => $commit_info) {
 
... ... foreach ($r as $commit_index => $commit_info) {
41 40 } }
42 41 file_put_contents(dirname(__FILE__) . "/git_log1.final", $final); file_put_contents(dirname(__FILE__) . "/git_log1.final", $final);
43 42
43 rg_log('OK!');
44
44 45 ?> ?>
File tests/git_log1.sh changed (mode: 100755) (index a6c668a..3b9e812)
... ... cd ..
63 63 echo "Building diff..." echo "Building diff..."
64 64 diff -u git_log1.final git_log1.expected > git_log1.diff diff -u git_log1.final git_log1.expected > git_log1.diff
65 65 if [ "${?}" != "0" ]; then if [ "${?}" != "0" ]; then
66 echo "Error: check git_log1.diff!"
66 echo "Error: check git_log1.diff (diff between .final and .expected)!"
67 67 exit 1 exit 1
68 68 fi fi
69 69
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/catalinux/rocketgit

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/catalinux/rocketgit

Clone this repository using git:
git clone git://git.rocketgit.com/user/catalinux/rocketgit

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main