List of commits:
Subject Hash Author Date (UTC)
Fixed rg_git_merge because it was broken 797a976065420525f9f2c6a096ae306ffa5ed78d Catalin(ux) M. BOIE 2019-09-30 19:50:41
Disable GC when serving requests from web/fetch/push; we will do it from cron fd16c96f5f0a6d24e0c6aaf45c5a02833579667a Catalin(ux) M. BOIE 2019-09-30 19:48:49
git: fixes display of filenames which are not UTF-8 valid 83b6f641a547a4652aad6e921486d2b91cffdb9f Catalin(ux) M. BOIE 2019-09-30 19:46:07
rg_change_pass missed a log file name e49fc9f8c896414098713e418205d97b2e594c1f Catalin(ux) M. BOIE 2019-09-22 09:32:59
totp: remove a double DELETE sql query and invalidate cache after we remove the data from db ff22d7ddabc1c64a37fcb1749f54321974b0f8d3 Catalin(ux) M. BOIE 2019-09-22 09:28:30
selinux: added map (for packs) 911b2cffa2d754d466a31693af71d6c58639dd9d Catalin(ux) M. BOIE 2019-09-22 06:58:44
Do not allow : char in user name 460b846752c03368990b60efbbf12f74e229bda5 Catalin(ux) M. BOIE 2019-09-22 05:58:37
Do not allow : char in repo name b072ba3cd6c46e2ee7d07dc5890c8671d8462a09 Catalin(ux) M. BOIE 2019-09-22 05:56:56
Fix an XSS in repo description ee2d11f0b16b436d9e64a0c5ac57361d25e098e1 Catalin(ux) M. BOIE 2019-09-22 05:45:11
Do not allow a user name to start with minus; strlen -> mb_strlen 755f2a47e99dc3a56cee90b424ee8a9bd84236f8 Catalin(ux) M. BOIE 2019-09-22 05:07:01
Do not allow a repo to start with minus; strlen -> mb_strlen 8ac45126805015c868ae8054ea328dc5a16cf31c Catalin(ux) M. BOIE 2019-09-22 05:06:41
Limit the desciption of the project to 100 chars to be able to pack more repos per page 1d2714726347b1eb9f113bd9c4d65d301d6502bd Catalin(ux) M. BOIE 2019-09-22 04:59:11
Changed CIF 47e6a7b3939898729d4344b8e3a01ac0dbd3e3b1 Catalin(ux) M. BOIE 2019-09-22 04:42:59
Added git_log1_strange.php to generate strange filenames 66083c9e3e6633c953bd5e77f28d993687ef2b73 Catalin(ux) M. BOIE 2019-09-17 20:01:10
tests: cosmetic stuff 7688f7b901e0fe3a94e2fcb62755af159212d053 Catalin(ux) M. BOIE 2019-09-17 20:00:04
If rg_dir_load returns false, propagate the error 6c8640b1200ae7859097e66dd73ba75857a845a5 Catalin(ux) M. BOIE 2019-09-17 19:48:25
rg_exec - do not return if the program closes stderr c619b6bc77b3a9bd1c4dea8a01ba3422620f4c90 Catalin(ux) M. BOIE 2019-09-17 19:47:26
rg_git_from_to: if to is empty, ignore it. 310506eab4b45a96cd75b69cfe72c54c7c5aa0e6 Catalin(ux) M. BOIE 2019-09-17 19:30:44
TODO changes 25a5232ed436fe23e7f21c8caa6934d3bfcbd6d7 Catalin(ux) M. BOIE 2019-09-17 19:25:33
Did some debug changes for git 25fbc904e16076cc6117a1bb900326344dba9d37 Catalin(ux) M. BOIE 2019-09-17 19:24:23
Commit 797a976065420525f9f2c6a096ae306ffa5ed78d - Fixed rg_git_merge because it was broken
Author: Catalin(ux) M. BOIE
Author date (UTC): 2019-09-30 19:50
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2019-09-30 19:50
Parent(s): fd16c96f5f0a6d24e0c6aaf45c5a02833579667a
Signer:
Signing key:
Signing status: N
Tree: 8fc89cf08ea8b619c6f676ec40213432d5cd7d9b
File Lines added Lines deleted
inc/git.inc.php 161 40
tests/pr_anon.php 7 6
File inc/git.inc.php changed (mode: 100644) (index 614f334..4c5129a)
... ... function rg_git_fatal($msg)
40 40 exit(1); exit(1);
41 41 } }
42 42
43 /*
44 * Locks a repo agains concurrent updates
45 * @timeout - in seconds
46 */
47 function rg_git_lock($repo_path, $timeout)
48 {
49 global $rg_git_lock;
50
51 rg_prof_start('git_lock');
52
53 $ret = FALSE;
54 while (1) {
55 $f = @fopen($repo_path . '/rg_lock', 'w');
56 if ($f === FALSE) {
57 rg_git_set_error('cannot lock repo (open)');
58 break;
59 }
60
61 $_s = time();
62 $_exit = FALSE;
63 while (1) {
64 $r = @flock($f, LOCK_EX | LOCK_NB, $would_block);
65 if ($r === TRUE)
66 break;
67
68 if ($would_block != 1)
69 rg_git_set_error('cannot lock repo (flock)');
70 $_exit = TRUE;
71 break;
72
73 $_now = time();
74 if ($_now > $_s + $timeout) {
75 $_exit = TRUE;
76 break;
77 }
78
79 sleep(1);
80 }
81 if ($_exit) {
82 fclose($f);
83 break;
84 }
85
86 $rg_git_lock[$repo_path] = $f;
87 $ret = TRUE;
88 break;
89 }
90
91 return $ret;
92 }
93
94 /*
95 * Unlocks a repo
96 */
97 function rg_git_unlock($repo_path)
98 {
99 global $rg_git_lock;
100
101 if (!isset($rg_git_lock[$repo_path]))
102 return;
103
104 $f = $rg_git_lock[$repo_path];
105 @flock($f, LOCK_UN);
106 fclose($f);
107 }
108
43 109 /* /*
44 110 * Returns the limit for diff for 'git log --patch' * Returns the limit for diff for 'git log --patch'
45 111 */ */
 
... ... function rg_git_short($ref)
73 139 return $ref; return $ref;
74 140 } }
75 141
142 /*
143 * 'master' -> 'refs/heads/master'
144 * 'refs/heads/master' -> same
145 */
146 function rg_git_name2ref($name)
147 {
148 if (strpos($name, '/') !== FALSE)
149 return $name;
150
151 return 'refs/heads/' . $name;
152 }
153
76 154 function rg_git_info($band, $msg) function rg_git_info($band, $msg)
77 155 { {
78 156 echo $band; echo $band;
 
... ... function rg_git_whitespace_ok($old, $new)
479 557 } }
480 558
481 559 /* /*
482 * Loads refs/heads/BRANCH
560 * Loads refs/heads/REF
483 561 */ */
484 562 function rg_git_load_ref($repo_path, $ref) function rg_git_load_ref($repo_path, $ref)
485 563 { {
 
... ... function rg_git_load_ref($repo_path, $ref)
503 581 } }
504 582
505 583 /* /*
506 * Returns a common ancestor between two commits
584 * Returns a common ancestor between two commits (FALSE on error)
507 585 * TODO: Unit testing * TODO: Unit testing
508 586 */ */
509 587 function rg_git_merge_base($repo_path, $a, $b) function rg_git_merge_base($repo_path, $a, $b)
 
... ... function rg_git_merge_base($repo_path, $a, $b)
566 644 /* /*
567 645 * Safely update a reference - used to update main namespace from other ns * Safely update a reference - used to update main namespace from other ns
568 646 * If @new is empty, we assume a delete * If @new is empty, we assume a delete
647 * Returns FALSE on error, TRUE on success.
569 648 * TODO: Unit testing * TODO: Unit testing
570 649 */ */
571 650 function rg_git_update_ref($repo_path, $ref, $old, $new, $reason) function rg_git_update_ref($repo_path, $ref, $old, $new, $reason)
572 651 { {
573 rg_prof_start("git_update_ref");
652 rg_prof_start('git_update_ref');
574 653 rg_log_enter("git_update_ref: ref=$ref old=$old new=$new reason=$reason"); rg_log_enter("git_update_ref: ref=$ref old=$old new=$new reason=$reason");
575 654
576 655 $ret = FALSE; $ret = FALSE;
 
... ... function rg_git_update_ref($repo_path, $ref, $old, $new, $reason)
582 661 if (!empty($reason)) if (!empty($reason))
583 662 $cmd .= " -m " . escapeshellarg($reason); $cmd .= " -m " . escapeshellarg($reason);
584 663
664 $ref = rg_git_name2ref($ref);
665
585 666 if (empty($new)) if (empty($new))
586 667 $cmd .= " -d " . escapeshellarg($ref); $cmd .= " -d " . escapeshellarg($ref);
587 668 else else
 
... ... function rg_git_update_ref($repo_path, $ref, $old, $new, $reason)
591 672 if (!empty($old)) if (!empty($old))
592 673 $cmd .= " " . escapeshellarg($old); $cmd .= " " . escapeshellarg($old);
593 674
594 $a = rg_exec($cmd, '', FALSE, FALSE);
595 if ($a['ok'] != 1) {
596 rg_git_set_error("error on update-ref (" . $a['errmsg'] . ")");
675 $r = rg_exec($cmd, '', FALSE, FALSE);
676 if ($r['ok'] != 1) {
677 rg_git_set_error(
678 'error on update-ref (' . $r['errmsg'] . ')');
597 679 break; break;
598 680 } }
599 681
 
... ... function rg_git_update_ref($repo_path, $ref, $old, $new, $reason)
602 684 } }
603 685
604 686 rg_log_exit(); rg_log_exit();
605 rg_prof_end("git_update_ref");
687 rg_prof_end('git_update_ref');
606 688 return $ret; return $ret;
607 689 } }
608 690
 
... ... function rg_git_log_simple($repo_path, $max, $from, $to, $also_patch, $files,
1065 1147
1066 1148 $cmd = RG_GIT_CMD . " --no-pager" $cmd = RG_GIT_CMD . " --no-pager"
1067 1149 . " --git-dir=" . escapeshellarg($repo_path) . " --git-dir=" . escapeshellarg($repo_path)
1150 . " -c core.quotePath=false"
1068 1151 . " log" . " log"
1069 1152 . " --find-copies" . " --find-copies"
1070 1153 . " --find-renames" . " --find-renames"
 
... ... function rg_git_log_simple($repo_path, $max, $from, $to, $also_patch, $files,
1184 1267 //rg_log_ml('DEBUG: numstat: ' . print_r($numstat, TRUE)); //rg_log_ml('DEBUG: numstat: ' . print_r($numstat, TRUE));
1185 1268 $tc = count($numstat); $tc = count($numstat);
1186 1269 while ($tc > 0) { while ($tc > 0) {
1187 $a = explode("\t", array_shift($numstat)); $tc--;
1270 $a = explode("\t", array_shift($numstat), 3); $tc--;
1188 1271 //rg_log_ml('DEBUG: a: ' . print_r($a, TRUE)); //rg_log_ml('DEBUG: a: ' . print_r($a, TRUE));
1189 1272
1190 1273 // We may have an empty commit // We may have an empty commit
 
... ... function rg_git_log($repo_path, $max, $from, $to, $also_patch, $patch_limit)
1395 1478 break; break;
1396 1479 } }
1397 1480
1398 //if ($rg_git_debug > 90)
1399 // rg_log_ml('DEBUG: stat: ' . print_r($stat, TRUE));
1481 if ($rg_git_debug > 90)
1482 rg_log_ml('DEBUG: stat: ' . print_r($stat, TRUE));
1400 1483 if (empty($from)) { if (empty($from)) {
1401 1484 $from = $stat[0]['vars']['sha1']; $from = $stat[0]['vars']['sha1'];
1402 1485 if ($rg_git_debug > 50) if ($rg_git_debug > 50)
 
... ... function rg_git_diff($id, $a, $template_file)
1647 1730 $ret .= "<tr>\n"; $ret .= "<tr>\n";
1648 1731 $ret .= " <td class=\"numbers\">...</td>\n"; $ret .= " <td class=\"numbers\">...</td>\n";
1649 1732 $ret .= " <td class=\"numbers\">...</td>\n"; $ret .= " <td class=\"numbers\">...</td>\n";
1650 $ret .= " <td style=\"background: #dddddd\" colspan=\"2\"><i>" . $ci['section'] . "</i></td>\n";
1733 $ret .= " <td style=\"background: #dddddd\" colspan=\"2\"><i>"
1734 . rg_xss_safe($ci['section']) . "</i></td>\n";
1651 1735 $ret .= "</tr>\n"; $ret .= "</tr>\n";
1652 1736 } }
1653 1737
 
... ... function rg_git_merge_without_conflict($repo_path, $a, $b)
2433 2517 } }
2434 2518
2435 2519 /* /*
2436 * Do a merge
2437 * @ff - 0 = no fast-forward, 1 = fast-forward allowed
2520 * Do a merge in a bare repo
2521 * @ff - 0 = fast-forward not allowed, 1 = fast-forward allowed
2438 2522 * @msg - merge message * @msg - merge message
2439 * Returns the output of the command or FALSE
2523 * Returns TRUE or FALSE
2524 * Thanks to https://stackoverflow.com/questions/7984986/git-merging-branches-in-a-bare-repository
2525 * TODO: we may prepend to @msg some more info (mr id etc.)
2440 2526 */ */
2441 function rg_git_merge($repo_path, $a, $b, $ff, $msg)
2527 function rg_git_merge($repo_path, $ref_name, $new, $ff, $msg)
2442 2528 { {
2443 2529 global $rg_git_zero; global $rg_git_zero;
2444 2530 global $rg_git_empty; global $rg_git_empty;
2445 2531
2446 2532 rg_prof_start('git_merge'); rg_prof_start('git_merge');
2447 rg_log_enter('git_merge' . ' a=' . $a . ' b=' . $b . ' ff=' . $ff
2448 . ' msg=' . $msg);
2533 rg_log_enter('git_merge' . ' ref_name=' . $ref_name
2534 . ' new=' . $new . ' ff=' . $ff . ' msg=' . $msg);
2449 2535
2450 2536 $ret = FALSE; $ret = FALSE;
2451 2537 while (1) { while (1) {
 
... ... function rg_git_merge($repo_path, $a, $b, $ff, $msg)
2454 2540 else else
2455 2541 $add = ' --git-dir=' . escapeshellarg($repo_path); $add = ' --git-dir=' . escapeshellarg($repo_path);
2456 2542
2457 $work_tree = rg_tmp_path('git_merge_' . rg_id(10));
2458 $r = @mkdir($work_tree, 0700, TRUE);
2459 if ($r !== TRUE) {
2460 rg_git_set_error('cannot create temporary dir for merge');
2543 // TODO
2544 //if ($ff == 1)
2545 // $add_ff = ' --ff';
2546 //else
2547 // $add_ff = ' --no-ff';
2548
2549 $r = rg_git_lock($repo_path, 60);
2550 if ($r === FALSE)
2551 break;
2552
2553 @unlink($repo_path . '/index');
2554 if (file_exists($repo_path . '/index')) {
2555 rg_git_set_error('cannot unlink index');
2461 2556 break; break;
2462 2557 } }
2463 $add .= ' --work-tree ' . escapeshellarg($work_tree);
2464 2558
2465 if ($ff == 1)
2466 $add_ff = ' --ff';
2467 else
2468 $add_ff = ' --no-ff';
2559 $mb = rg_git_merge_base($repo_path, $ref_name, $new);
2560 if ($mb === FALSE)
2561 break;
2469 2562
2470 $cmd = 'git'
2471 . $add
2472 . ' merge'
2473 . $add_ff
2474 . ' --stat'
2475 . ' -m ' . escapeshellarg($msg)
2476 . ' ' . escapeshellarg($a)
2477 . ' ' . escapeshellarg($b);
2478 $a = rg_exec($cmd, '', FALSE, FALSE);
2479 rg_rmdir($work_tree);
2480 if ($a['ok'] != 1) {
2481 rg_git_set_error('error on git merge ('
2482 . $a['errmsg'] . ')');
2563 rg_log('DEBUG: mb=' . $mb);
2564
2565 $e_mb = escapeshellarg($mb);
2566 $e_ref_name = escapeshellarg($ref_name);
2567 $e_new = escapeshellarg($new);
2568
2569 $cmd = RG_GIT_CMD
2570 . $add . ' read-tree -i -m '
2571 . $e_mb . ' ' . $e_ref_name . ' ' . $e_new;
2572 $r = rg_exec($cmd, '', FALSE, FALSE);
2573 if ($r['ok'] != 1) {
2574 rg_git_set_error('error on merge (read-tree) ('
2575 . $r['errmsg'] . ')');
2483 2576 break; break;
2484 2577 } }
2485 2578
2486 $ret = trim($a['data']);
2579 $cmd = RG_GIT_CMD . $add . ' write-tree';
2580 $r = rg_exec($cmd, '', FALSE, FALSE);
2581 if ($r['ok'] != 1) {
2582 rg_git_set_error('error on merge (write-tree) ('
2583 . $r['errmsg'] . ')');
2584 break;
2585 }
2586 $tree = $r['data'];
2587
2588 $cmd = RG_GIT_CMD . $add . ' commit-tree '
2589 . escapeshellarg($tree)
2590 . ' -p ' . $e_ref_name . ' -p ' . $e_new
2591 . ' -m ' . escapeshellarg($msg);
2592 $r = rg_exec($cmd, '', FALSE, FALSE);
2593 if ($r['ok'] != 1) {
2594 rg_git_set_error('error on merge (commit-tree) ('
2595 . $r['errmsg'] . ')');
2596 break;
2597 }
2598 $commit = $r['data'];
2599
2600 $r = rg_git_update_ref($repo_path, $ref_name,
2601 '' /*old*/, $new, $msg);
2602 if ($r !== TRUE)
2603 break;
2604
2605 $ret = TRUE;
2487 2606 break; break;
2488 2607 } }
2608 @unlink($repo_path . '/index');
2609 rg_git_unlock($repo_path);
2489 2610
2490 2611 rg_log_exit(); rg_log_exit();
2491 2612 rg_prof_end('git_merge'); rg_prof_end('git_merge');
File tests/pr_anon.php changed (mode: 100644) (index 27a90da..5dcac32)
... ... rg_log_exit();
85 85
86 86 rg_log(''); rg_log('');
87 87 rg_log_enter('Preparing repo...'); rg_log_enter('Preparing repo...');
88 $r = rg_exec('rm -rf temp_repos/pr_anon'
89 . ' && mkdir temp_repos/pr_anon'
90 . ' && cd temp_repos/pr_anon'
88 $r = rg_exec('mkdir -p temp_repos && cd temp_repos'
89 . ' && rm -rf pr_anon'
90 . ' && mkdir pr_anon'
91 . ' && cd pr_anon'
91 92 . ' && git init' . ' && git init'
92 93 . ' && git remote add origin_ssh ' . ' && git remote add origin_ssh '
93 94 . ' ssh://rocketgit@' . $rg_ssh_host . ':' . $rg_ssh_port . ' ssh://rocketgit@' . $rg_ssh_host . ':' . $rg_ssh_port
 
... ... $headers = array();
166 167 $r = do_req($test_url . $url . $mri['id'] . '?t=pr_anon', $data, $headers); $r = do_req($test_url . $url . $mri['id'] . '?t=pr_anon', $data, $headers);
167 168 if (!strstr($r['body'], 'This pull request can be merged without conflicts')) { if (!strstr($r['body'], 'This pull request can be merged without conflicts')) {
168 169 rg_log_ml('r: ' . print_r($r, TRUE)); rg_log_ml('r: ' . print_r($r, TRUE));
169 rg_log('Pull request does not appear as mergeable');
170 rg_log('Merge request does not appear as mergeable');
170 171 exit(1); exit(1);
171 172 } }
172 173 rg_log_exit(); rg_log_exit();
173 174
174 175
175 176 rg_log(''); rg_log('');
176 rg_log_enter('Merging pull request...');
177 rg_log_enter('Merging merge request...');
177 178 $data = array('token' => $r['tokens']['mr_merge'], $data = array('token' => $r['tokens']['mr_merge'],
178 179 'merge_ff' => 0, 'merge_msg' => 'This is the merge message <xss>'); 'merge_ff' => 0, 'merge_msg' => 'This is the merge message <xss>');
179 180 $r = do_req($test_url . $url . $mri['id'] . '/merge', $data, $headers); $r = do_req($test_url . $url . $mri['id'] . '/merge', $data, $headers);
 
... ... while (1) {
193 194 break; break;
194 195
195 196 if ($tries == 10) { if ($tries == 10) {
196 rg_log('merge_request was not marked as done!');
197 rg_log('merge_request was not marked as done in db!');
197 198 exit(1); exit(1);
198 199 } }
199 200 $tries++; $tries++;
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