File TODO changed (mode: 100644) (index 15db99d..0fbb7e3) |
1 |
1 |
== Where I stopped last time == |
== Where I stopped last time == |
|
2 |
|
[ ] Protect emails from commits?! |
|
3 |
|
[ ] Stop logging passwords! |
2 |
4 |
[ ] /user/catalinux/test1/source/tree/blob/"xx/"yy" pe rocketgit.com |
[ ] /user/catalinux/test1/source/tree/blob/"xx/"yy" pe rocketgit.com |
3 |
5 |
generates errors. something regargin ls-tree that outputs nothing. |
generates errors. something regargin ls-tree that outputs nothing. |
4 |
6 |
This is another problem. If is empty, we should not enter foreach! |
This is another problem. If is empty, we should not enter foreach! |
|
7 |
|
[ ] Seems that after I create a repo and pushed something anonymous, some files |
|
8 |
|
were not readable by others. :( |
|
9 |
|
[ ] mr: where is the uid of the user that did the push?! |
|
10 |
|
Is the anon push by a user supported?! |
|
11 |
|
added merge_requests.who (default 0) |
|
12 |
|
[ ] mr: when pushing, also show the link to the mr? |
|
13 |
|
We do not have it because we add an event. |
|
14 |
|
[ ] mr: after a push is done, add an event to generate the status if a mr can |
|
15 |
|
be merged. Or be lazy till first access? Maybe when we are idle. |
|
16 |
|
[ ] mr: we need token in merge form! Done, check. |
|
17 |
|
[ ] repo stats must not be generated in web. It may take a lot of time. |
|
18 |
|
We must do them incrementally, from cron, and only max N commits |
|
19 |
|
per repo in one run. |
|
20 |
|
[ ] --work-dir must be created in some temporary folder. |
|
21 |
|
[ ] mr: After merging, shoul we delete the namespace? |
|
22 |
|
[ ] mr: do I test if the user "pressing" merge has the right to do the merge? |
|
23 |
|
[ ] mr: seems I do not store the merge requests into mr/<id>! |
5 |
24 |
[ ] |
[ ] |
6 |
25 |
|
|
7 |
26 |
== BEFORE NEXT RELEASE == |
== BEFORE NEXT RELEASE == |
|
27 |
|
[ ] LOW: do we clean temporary files automatically? |
|
28 |
|
[ ] LOW: when pushing, in history add a link to the pull request (if anon). |
|
29 |
|
[ ] LOW: commit on web: enforce subject (50 chars), do wrap (72), |
|
30 |
|
enforce signoffs or other headers. Add a marker to force no wrap. |
|
31 |
|
A pull must have name, e-mail, why, shorlog, diffstat. |
|
32 |
|
[ ] LOW: mr: notify the owner of the pull request (if not anonymous)? |
|
33 |
|
[ ] LOW: when destroying a repo, destroy the cache by path (git caches by path) |
|
34 |
|
[ ] LOW: /usr/share/rocketgit/root/themes/default//usr/share/rocketgit/root/themes/default/hints/list/header.html |
|
35 |
|
[ ] LOW: mr: private pull requests? |
|
36 |
|
[ ] LOW: mr: get rid of namespaces? |
|
37 |
|
[ ] LOW: mr: add possibility to reject a pull request. |
|
38 |
|
[ ] LOW: mr: add the right to reject pull requests. |
|
39 |
|
[ ] LOW: mr: allow adding comments for pull requests. |
|
40 |
|
[ ] LOW: mr: Add after "Against ref" the sha/subject of the commit. |
|
41 |
|
[ ] LOW: mr: allow the anonymous users to delete a pull request by providing |
|
42 |
|
a link. |
|
43 |
|
[ ] LOW: mr: allow the owner to remove a pull request. |
|
44 |
|
[ ] LOW: mr: Use rg_git_request_pull to generate a pull request from a onw repo. |
|
45 |
|
Example: git request-pull master~4 git://localhost/user/catab/testpull |
|
46 |
|
We must present a list of commits, so the user can choose 'start' and |
|
47 |
|
'end'. |
|
48 |
|
[ ] LOW: do not make the e-mail mandatory. |
|
49 |
|
[ ] LOW: mr: add PGP signature in the pull request. |
|
50 |
|
[ ] LOW: mr: "git diff ...otherbranch" - should I also use this to show |
|
51 |
|
what a merge will do? This is different from git log old..new |
|
52 |
|
when branch tip was updated. |
|
53 |
|
[ ] LOW: optimization for merge_base: if 'against' == HEAD, just return 'against' |
|
54 |
|
[ ] LOW: signal when a pull request from rocketgit was fetched? |
|
55 |
|
[ ] LOW: pull rquests: subject and body must be in another div. |
|
56 |
|
[ ] LOW: rebase: add rebase on a branch (test for conflicts first). |
|
57 |
|
[ ] LOW: mr: add another type of merge: merge a branch into another. |
|
58 |
|
[ ] LOW: mr: add to history when a merge is done. |
|
59 |
|
[ ] MED: mr: a push/merge must destroy the cache git::sha1($repo_path) |
|
60 |
|
[ ] LOW: mr: add caching for mergeability status. |
|
61 |
|
[ ] LOW: "mode:" must be also shown nice |
|
62 |
|
[ ] LOW: mr: commits must be isolated in div islands with some background |
|
63 |
|
[ ] LOW: mr: maybe files should be listen on the right of the commit info? |
|
64 |
|
[ ] LOW: mr: Commits must be indented somehow. |
|
65 |
|
[ ] LOW: mr: between diff and "Commit xxx" the is no space! |
|
66 |
|
[ ] LOW: In log/line.html, subject should also be a link to the commit |
|
67 |
|
[ ] LOW: mr: allow user to resolve conflicts online? |
|
68 |
|
[ ] LOW: mr: error messages must still show the merge information. |
|
69 |
|
[ ] mr: what if a user pushes agains a tag instead of a branch?! |
|
70 |
|
rg_git_short will not work correctly! |
|
71 |
|
[ ] mr: test if a merge was already merged. |
|
72 |
|
[ ] Do we call rg_git_reference when a push takes place? |
|
73 |
|
[ ] Add rewind/rebase rights? |
|
74 |
|
[ ] for any tree sha, add a link to show the tree. |
|
75 |
|
[ ] mr: add possibility to reject a pull request (and move it to the inactive |
|
76 |
|
queue). |
|
77 |
|
[ ] mr: when a push is taking place, all mrs must invalidate merge_cleanly flag |
|
78 |
|
but only if are affected by the branch! |
|
79 |
|
Also, revalidate if the merge is ok and if not, maybe notify the owner |
|
80 |
|
to give her/him the chance to redo it? Maybe sent her/him an access |
|
81 |
|
code to be able to close it? |
|
82 |
|
[ ] notes: Error: Unknown refname type provided [refs/notes/commits] |
|
83 |
|
[ ] notes: Right ro allow notes pushing? |
|
84 |
|
[ ] repo: delete 'mr's when deleting a repo. |
|
85 |
|
[ ] bug: allow deleting |
|
86 |
|
[ ] final-form: add a flag to the repo that is not maintained anymore. |
|
87 |
|
[ ] Scellow: dark theme (https://userstyles.org/styles/37035/github-dark) |
8 |
88 |
[ ] Add some hints on how to recover the password for admin user! |
[ ] Add some hints on how to recover the password for admin user! |
9 |
89 |
Make the script to allow to change pass for any user? |
Make the script to allow to change pass for any user? |
10 |
90 |
Think about multiple admins. |
Think about multiple admins. |
|
256 |
336 |
[ ] unit test: check if the log is correctly generated after a push. |
[ ] unit test: check if the log is correctly generated after a push. |
257 |
337 |
I suspect some rights problems. |
I suspect some rights problems. |
258 |
338 |
[ ] pr: I should add also the user who made the pull request |
[ ] pr: I should add also the user who made the pull request |
259 |
|
or anonymous. Also, IP must be shown also to the owner. |
|
|
339 |
|
or anonymous. |
260 |
340 |
[ ] After some releases, remove any trace of q_merge_requests! |
[ ] After some releases, remove any trace of q_merge_requests! |
261 |
341 |
[ ] pr: seems now I go through /var/lib/rocketgit/q_merge_requests |
[ ] pr: seems now I go through /var/lib/rocketgit/q_merge_requests |
262 |
342 |
We should use events! And then get rid of this dir. |
We should use events! And then get rid of this dir. |
263 |
343 |
What happends now? |
What happends now? |
264 |
344 |
Seems I need to replace rg_mr_queue_add with rg_mr_create. |
Seems I need to replace rg_mr_queue_add with rg_mr_create. |
265 |
345 |
Cron loads merge requests from files and calls mr_queue_add. |
Cron loads merge requests from files and calls mr_queue_add. |
266 |
|
[ ] Add avatars for notes and bugs. |
|
|
346 |
|
[ ] Add avatars for bugs. |
267 |
347 |
[ ] Allow an admin to run extra hooks by adding _them_ info |
[ ] Allow an admin to run extra hooks by adding _them_ info |
268 |
348 |
/var/lib/rocketgit/extra_hooks/{update,post-receive,...}/ folder. |
/var/lib/rocketgit/extra_hooks/{update,post-receive,...}/ folder. |
269 |
349 |
[ ] check 'man git-receive-pack' for gpg (about signed pushes). |
[ ] check 'man git-receive-pack' for gpg (about signed pushes). |
|
307 |
387 |
- Select "Review" - optional |
- Select "Review" - optional |
308 |
388 |
- If selected, show the diff |
- If selected, show the diff |
309 |
389 |
- Add a commit message |
- Add a commit message |
310 |
|
- Notify commiters? |
|
|
390 |
|
- Notify committers? |
311 |
391 |
Where should the "Pull requests" menu be? |
Where should the "Pull requests" menu be? |
312 |
392 |
Show some info about the merge request: authors, files, diffstat etc. |
Show some info about the merge request: authors, files, diffstat etc. |
313 |
393 |
4 pieces of information: src/dst repo/branch. |
4 pieces of information: src/dst repo/branch. |
|
... |
... |
But, we have a problem with the expiration time! |
1024 |
1104 |
lists without pagination? |
lists without pagination? |
1025 |
1105 |
[ ] pg_fetch_assoc returns FALSE if error or no more rows. |
[ ] pg_fetch_assoc returns FALSE if error or no more rows. |
1026 |
1106 |
We must know the difference! |
We must know the difference! |
1027 |
|
[ ] Finish high level sql function. |
|
1028 |
1107 |
[ ] No caching for keys.php? If we add one, update first_use only if needed. |
[ ] No caching for keys.php? If we add one, update first_use only if needed. |
1029 |
1108 |
[ ] Rate limit at least login operations to prevent brute force passwords. |
[ ] Rate limit at least login operations to prevent brute force passwords. |
1030 |
1109 |
Because the attack may come from several IPs, it is tempting to |
Because the attack may come from several IPs, it is tempting to |
File inc/git.inc.php changed (mode: 100644) (index 4d31466..528eaae) |
... |
... |
function rg_git_fatal($msg) |
34 |
34 |
exit(1); |
exit(1); |
35 |
35 |
} |
} |
36 |
36 |
|
|
|
37 |
|
/* |
|
38 |
|
* Returns the short version for a reference |
|
39 |
|
*/ |
|
40 |
|
function rg_git_short($ref) |
|
41 |
|
{ |
|
42 |
|
if (strncmp($ref, 'refs/heads/', 11) == 0) |
|
43 |
|
return substr($ref, 11); |
|
44 |
|
|
|
45 |
|
if (strncmp($ref, '/refs/heads/', 12) == 0) |
|
46 |
|
return substr($ref, 12); |
|
47 |
|
|
|
48 |
|
return $ref; |
|
49 |
|
} |
|
50 |
|
|
37 |
51 |
function rg_git_info($msg) |
function rg_git_info($msg) |
38 |
52 |
{ |
{ |
39 |
53 |
$x = explode("\n", trim($msg)); |
$x = explode("\n", trim($msg)); |
|
... |
... |
function rg_git_rev($rev) |
263 |
277 |
function rg_git_reference($refname) |
function rg_git_reference($refname) |
264 |
278 |
{ |
{ |
265 |
279 |
// We do not accept '..' chars |
// We do not accept '..' chars |
266 |
|
if (preg_match('/\.\./', $refname) !== 0) { |
|
|
280 |
|
if (strstr($refname, '..')) { |
267 |
281 |
rg_git_set_error('we do not accept \'..\' inside the ref name'); |
rg_git_set_error('we do not accept \'..\' inside the ref name'); |
268 |
282 |
return FALSE; |
return FALSE; |
269 |
283 |
} |
} |
270 |
284 |
|
|
271 |
|
// We do not accept '/.' chars |
|
272 |
|
if (preg_match('/\/\./', $refname) !== 0) { |
|
|
285 |
|
if (strstr($refname, '/.')) { |
273 |
286 |
rg_git_set_error('we do not accept \'/.\' inside the ref name'); |
rg_git_set_error('we do not accept \'/.\' inside the ref name'); |
274 |
287 |
return FALSE; |
return FALSE; |
275 |
288 |
} |
} |
276 |
289 |
|
|
277 |
|
// We do not accept '\\' chars |
|
278 |
|
if (preg_match('/\\\\/', $refname) !== 0) { |
|
|
290 |
|
if (strstr($refname, '\\\\')) { |
279 |
291 |
rg_git_set_error('we do not accept \'\\\\\' inside the ref name'); |
rg_git_set_error('we do not accept \'\\\\\' inside the ref name'); |
280 |
292 |
return FALSE; |
return FALSE; |
281 |
293 |
} |
} |
|
... |
... |
function rg_git_rev_ok($rev) |
312 |
324 |
|
|
313 |
325 |
$ret = FALSE; |
$ret = FALSE; |
314 |
326 |
while (1) { |
while (1) { |
315 |
|
$cmd = "git rev-parse --verify '" . $rev . "'"; |
|
|
327 |
|
$cmd = 'git rev-parse --verify ' . escapeshellarg($rev); |
316 |
328 |
$a = rg_exec($cmd); |
$a = rg_exec($cmd); |
317 |
329 |
if ($a['ok'] != 1) { |
if ($a['ok'] != 1) { |
318 |
330 |
rg_git_set_error("error on rev-parse (" . $a['errmsg'] . ")"); |
rg_git_set_error("error on rev-parse (" . $a['errmsg'] . ")"); |
319 |
331 |
break; |
break; |
320 |
332 |
} |
} |
321 |
333 |
|
|
322 |
|
$ret = TRUE; |
|
|
334 |
|
$ret = trim($a['data']); |
323 |
335 |
break; |
break; |
324 |
336 |
} |
} |
325 |
337 |
|
|
|
... |
... |
function rg_git_whitespace_ok($old, $new) |
364 |
376 |
return $ret; |
return $ret; |
365 |
377 |
} |
} |
366 |
378 |
|
|
367 |
|
// TODO: Unit testing |
|
368 |
|
function rg_git_merge_base($old, $new) |
|
|
379 |
|
/* |
|
380 |
|
* Loads refs/heads/BRANCH |
|
381 |
|
*/ |
|
382 |
|
function rg_git_load_ref($repo_path, $ref) |
369 |
383 |
{ |
{ |
370 |
|
rg_prof_start("git_merge_base"); |
|
371 |
|
rg_log_enter("git_merge_base: old=$old new=$new"); |
|
|
384 |
|
global $rg_git_empty; |
|
385 |
|
|
|
386 |
|
$b = rg_git_reference($ref); |
|
387 |
|
if ($b === FALSE) |
|
388 |
|
return FALSE; |
|
389 |
|
|
|
390 |
|
$b = rg_git_short($b); |
|
391 |
|
$path = $repo_path . '/refs/heads/' . $b; |
|
392 |
|
$r = @file_get_contents($path); |
|
393 |
|
if ($r === FALSE) { |
|
394 |
|
// probably is a sha1 |
|
395 |
|
$r = $ref; |
|
396 |
|
} |
|
397 |
|
|
|
398 |
|
$ret = trim($r); |
|
399 |
|
rg_log('DEBUG: git_load_ref[' . $ref . ']=' . $ret); |
|
400 |
|
return $ret; |
|
401 |
|
} |
|
402 |
|
|
|
403 |
|
/* |
|
404 |
|
* Returns a common ancestor between two commits |
|
405 |
|
* TODO: Unit testing |
|
406 |
|
*/ |
|
407 |
|
function rg_git_merge_base($repo_path, $a, $b) |
|
408 |
|
{ |
|
409 |
|
global $rg_git_zero; |
|
410 |
|
global $rg_git_empty; |
|
411 |
|
|
|
412 |
|
rg_prof_start('git_merge_base'); |
|
413 |
|
rg_log_enter('git_merge_base' . ' a=' . $a . ' b=' . $b); |
372 |
414 |
|
|
373 |
415 |
$ret = FALSE; |
$ret = FALSE; |
374 |
416 |
while (1) { |
while (1) { |
375 |
|
$cmd = "git merge-base " . $old . " " . $new; |
|
|
417 |
|
if (empty($repo_path)) |
|
418 |
|
$add = ''; |
|
419 |
|
else |
|
420 |
|
$add = ' --git-dir=' . escapeshellarg($repo_path); |
|
421 |
|
|
|
422 |
|
if (!empty($repo_path)) { |
|
423 |
|
$head = rg_git_load_ref($repo_path, $a); |
|
424 |
|
if ($head === FALSE) |
|
425 |
|
break; |
|
426 |
|
|
|
427 |
|
$key = 'git' |
|
428 |
|
. '::' . sha1($repo_path) |
|
429 |
|
. '::' . 'merge-base' |
|
430 |
|
. '::' . $head . '::' . $b; |
|
431 |
|
$r = rg_cache_get($key); |
|
432 |
|
if ($r !== FALSE) { |
|
433 |
|
$ret = $r; |
|
434 |
|
break; |
|
435 |
|
} |
|
436 |
|
} |
|
437 |
|
|
|
438 |
|
$cmd = 'git' |
|
439 |
|
. $add |
|
440 |
|
. ' merge-base' |
|
441 |
|
. ' ' . escapeshellarg($a) |
|
442 |
|
. ' ' . escapeshellarg($b); |
376 |
443 |
$a = rg_exec($cmd); |
$a = rg_exec($cmd); |
377 |
444 |
if ($a['ok'] != 1) { |
if ($a['ok'] != 1) { |
378 |
|
rg_git_set_error("error on merge-base (" . $a['errmsg'] . ")"); |
|
|
445 |
|
rg_git_set_error('error on git merge_base (' |
|
446 |
|
. $a['errmsg'] . ')'); |
379 |
447 |
break; |
break; |
380 |
448 |
} |
} |
381 |
449 |
|
|
382 |
450 |
$ret = trim($a['data']); |
$ret = trim($a['data']); |
|
451 |
|
|
|
452 |
|
if (!empty($repo_path)) |
|
453 |
|
rg_cache_set($key, $ret, RG_SOCKET_NO_WAIT); |
|
454 |
|
|
383 |
455 |
break; |
break; |
384 |
456 |
} |
} |
385 |
457 |
|
|
386 |
458 |
rg_log_exit(); |
rg_log_exit(); |
387 |
|
rg_prof_end("git_merge_base"); |
|
|
459 |
|
rg_prof_end('git_merge_base'); |
388 |
460 |
return $ret; |
return $ret; |
389 |
461 |
} |
} |
390 |
462 |
|
|
|
... |
... |
function rg_git_merge_base($old, $new) |
393 |
465 |
* If @new is empty, we assume a delete |
* If @new is empty, we assume a delete |
394 |
466 |
* TODO: Unit testing |
* TODO: Unit testing |
395 |
467 |
*/ |
*/ |
396 |
|
function rg_git_update_ref($ref, $old, $new, $reason) |
|
|
468 |
|
function rg_git_update_ref($repo_path, $ref, $old, $new, $reason) |
397 |
469 |
{ |
{ |
398 |
470 |
rg_prof_start("git_update_ref"); |
rg_prof_start("git_update_ref"); |
399 |
471 |
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"); |
400 |
472 |
|
|
401 |
473 |
$ret = FALSE; |
$ret = FALSE; |
402 |
474 |
while (1) { |
while (1) { |
403 |
|
$cmd = "git update-ref"; |
|
|
475 |
|
$cmd = 'git --git-dir=' . escapeshellarg($repo_path); |
|
476 |
|
$cmd .= ' update-ref'; |
|
477 |
|
|
404 |
478 |
if (!empty($reason)) |
if (!empty($reason)) |
405 |
479 |
$cmd .= " -m " . escapeshellarg($reason); |
$cmd .= " -m " . escapeshellarg($reason); |
406 |
480 |
|
|
|
... |
... |
function rg_git_update_ref($ref, $old, $new, $reason) |
427 |
501 |
return $ret; |
return $ret; |
428 |
502 |
} |
} |
429 |
503 |
|
|
|
504 |
|
/* |
|
505 |
|
* git shortlog command |
|
506 |
|
*/ |
|
507 |
|
function rg_git_shortlog($repo_path, $a, $b) |
|
508 |
|
{ |
|
509 |
|
rg_prof_start('git_shortlog'); |
|
510 |
|
rg_log_enter('git_shortlog: a=' . $a . ' b=' . $b); |
|
511 |
|
|
|
512 |
|
$ret = FALSE; |
|
513 |
|
while (1) { |
|
514 |
|
$cmd = 'git shortlog' |
|
515 |
|
. ' --git-dir=' . escapeshellarg($repo_path) |
|
516 |
|
. ' ' . escapeshellarg($a) . '..' . escapeshellarg($b); |
|
517 |
|
$r = rg_exec($cmd); |
|
518 |
|
if ($r['ok'] != 1) { |
|
519 |
|
rg_git_set_error('error on shortlog (' . $r['errmsg'] . ')'); |
|
520 |
|
break; |
|
521 |
|
} |
|
522 |
|
|
|
523 |
|
$ret = trim($r['data']); |
|
524 |
|
break; |
|
525 |
|
} |
|
526 |
|
|
|
527 |
|
rg_log_exit(); |
|
528 |
|
rg_prof_end("git_shortlog"); |
|
529 |
|
return $ret; |
|
530 |
|
} |
|
531 |
|
|
430 |
532 |
/* |
/* |
431 |
533 |
* Returns a tree (git ls-tree) |
* Returns a tree (git ls-tree) |
432 |
534 |
*/ |
*/ |
|
... |
... |
function rg_git_log($path, $max, $from, $to, $also_patch) |
698 |
800 |
|
|
699 |
801 |
$ret = FALSE; |
$ret = FALSE; |
700 |
802 |
while (1) { |
while (1) { |
701 |
|
if (!file_exists($path . "/refs/heads/master")) { |
|
702 |
|
if (!file_exists($path . "/.git/refs/heads/master")) { |
|
703 |
|
rg_log("Repo is empty."); |
|
704 |
|
$ret = array(); |
|
705 |
|
break; |
|
706 |
|
} |
|
707 |
|
} |
|
708 |
|
|
|
709 |
|
$max_count = ($max == 0) ? "" : " --max-count=$max"; |
|
710 |
|
$patches = $also_patch ? " --patch" : " --shortstat"; |
|
|
803 |
|
$test_for_master = TRUE; |
711 |
804 |
|
|
712 |
805 |
if (empty($from) && empty($to)) { |
if (empty($from) && empty($to)) { |
|
806 |
|
rg_log('from/to empty'); |
713 |
807 |
$from_to = ''; |
$from_to = ''; |
|
808 |
|
} else if (empty($from)) { |
|
809 |
|
rg_log('from empty'); |
|
810 |
|
$from_to = ' ' . $to; |
|
811 |
|
} else if (strcmp($from, $rg_git_zero) == 0) { |
|
812 |
|
rg_log('from zero'); |
|
813 |
|
$from_to = ' ' . $rg_git_empty . '..' . $to; |
|
814 |
|
$test_for_master = FALSE; |
714 |
815 |
} else { |
} else { |
715 |
|
if (empty($from)) |
|
716 |
|
$from_to = ' ' . $to; |
|
717 |
|
else if (strcmp($from, $rg_git_zero) == 0) |
|
718 |
|
$from_to = ' ' . $rg_git_empty . '..' . $to; |
|
719 |
|
else |
|
720 |
|
$from_to = ' ' . $from . '..' . $to; |
|
|
816 |
|
$from_to = ' ' . $from . '..' . $to; |
|
817 |
|
} |
|
818 |
|
|
|
819 |
|
if ($test_for_master) { |
|
820 |
|
if (!file_exists($path . "/refs/heads/master")) { |
|
821 |
|
if (!file_exists($path . "/.git/refs/heads/master")) { |
|
822 |
|
rg_log("Repo is empty."); |
|
823 |
|
$ret = array(); |
|
824 |
|
break; |
|
825 |
|
} |
|
826 |
|
} |
721 |
827 |
} |
} |
722 |
828 |
|
|
|
829 |
|
$max_count = ($max == 0) ? "" : " --max-count=$max"; |
|
830 |
|
$patches = $also_patch ? " --patch" : " --shortstat"; |
|
831 |
|
|
723 |
832 |
$cmd = "git --no-pager" |
$cmd = "git --no-pager" |
724 |
833 |
. " --git-dir=" . escapeshellarg($path) |
. " --git-dir=" . escapeshellarg($path) |
725 |
834 |
. " log" |
. " log" |
|
... |
... |
function rg_git_log($path, $max, $from, $to, $also_patch) |
730 |
839 |
. $patches |
. $patches |
731 |
840 |
. " --pretty=\"format:" |
. " --pretty=\"format:" |
732 |
841 |
. "%x00-=ROCKETGIT=-%x00" |
. "%x00-=ROCKETGIT=-%x00" |
|
842 |
|
. "sha1:%H%x00\"\"" |
733 |
843 |
. "sha1_short:%h%x00\"\"" |
. "sha1_short:%h%x00\"\"" |
734 |
|
. "sha1_long:%H%x00\"\"" |
|
735 |
|
. "tree:%t%x00\"\"" |
|
|
844 |
|
. "tree:%T%x00\"\"" |
|
845 |
|
. "tree_short:%t%x00\"\"" |
|
846 |
|
. "parents:%P%x00\"\"" |
736 |
847 |
. "parents_short:%p%x00\"\"" |
. "parents_short:%p%x00\"\"" |
737 |
|
. "parents_long:%P%x00\"\"" |
|
738 |
848 |
. "author name:%aN%x00\"\"" |
. "author name:%aN%x00\"\"" |
739 |
849 |
. "author email:%aE%x00\"\"" |
. "author email:%aE%x00\"\"" |
740 |
850 |
. "author date:%at%x00\"\"" |
. "author date:%at%x00\"\"" |
|
... |
... |
function rg_git_log($path, $max, $from, $to, $also_patch) |
742 |
852 |
. "committer email:%ce%x00\"\"" |
. "committer email:%ce%x00\"\"" |
743 |
853 |
. "committer date:%ct%x00\"\"" |
. "committer date:%ct%x00\"\"" |
744 |
854 |
. "encoding:%e%x00\"\"" |
. "encoding:%e%x00\"\"" |
|
855 |
|
. "ref_names:%d%x00\"\"" |
|
856 |
|
. "sign_key:%GK%x00\"\"" |
745 |
857 |
. "subject:%s%x00\"\"" |
. "subject:%s%x00\"\"" |
746 |
858 |
. "body:%b%x00\"\"" |
. "body:%b%x00\"\"" |
747 |
859 |
. "notes:%N%x00\"\"" |
. "notes:%N%x00\"\"" |
|
... |
... |
function rg_git_log($path, $max, $from, $to, $also_patch) |
773 |
885 |
// vars |
// vars |
774 |
886 |
$y['vars']['lines_add'] = 0; |
$y['vars']['lines_add'] = 0; |
775 |
887 |
$y['vars']['lines_del'] = 0; |
$y['vars']['lines_del'] = 0; |
776 |
|
$y['vars']['files_cahnged'] = 0; |
|
777 |
888 |
$x = explode ("\0", trim($parts[0])); |
$x = explode ("\0", trim($parts[0])); |
778 |
889 |
$count = count($x); |
$count = count($x); |
779 |
890 |
for ($i = 0; $i < $count - 1; $i++) { |
for ($i = 0; $i < $count - 1; $i++) { |
|
... |
... |
function rg_git_log($path, $max, $from, $to, $also_patch) |
795 |
906 |
|
|
796 |
907 |
$y['vars']['lines_add'] = $_extra['lines_add']; |
$y['vars']['lines_add'] = $_extra['lines_add']; |
797 |
908 |
$y['vars']['lines_del'] = $_extra['lines_del']; |
$y['vars']['lines_del'] = $_extra['lines_del']; |
798 |
|
// TODO: add files_cahnged field! |
|
799 |
909 |
} else { |
} else { |
800 |
910 |
// stortstat |
// stortstat |
801 |
911 |
rg_log('DEBUG parts[1]: ' . print_r($parts[1], TRUE)); |
rg_log('DEBUG parts[1]: ' . print_r($parts[1], TRUE)); |
802 |
912 |
$t = explode(',', $parts[1]); |
$t = explode(',', $parts[1]); |
803 |
|
$y['vars']['files_changed'] = intval($t[0]); |
|
804 |
913 |
|
|
805 |
914 |
for ($i = 1; $i < 3; $i++) { |
for ($i = 1; $i < 3; $i++) { |
806 |
915 |
if (!isset($t[$i])) |
if (!isset($t[$i])) |
|
... |
... |
function rg_git_files($old, $new) |
944 |
1053 |
/* |
/* |
945 |
1054 |
* Nice diff per file |
* Nice diff per file |
946 |
1055 |
* Outputs the result of replacing variables in a template with real variables |
* Outputs the result of replacing variables in a template with real variables |
|
1056 |
|
* @id - uniq id, most of the time the commit sha1; used to differentiate |
|
1057 |
|
* between same files in different commits. |
947 |
1058 |
* @a - output of rg_git_diff2array[index]['files'] |
* @a - output of rg_git_diff2array[index]['files'] |
948 |
1059 |
* TODO: Switch to rg_template_table? |
* TODO: Switch to rg_template_table? |
949 |
1060 |
*/ |
*/ |
950 |
|
function rg_git_diff($a, $template_file) |
|
|
1061 |
|
function rg_git_diff($id, $a, $template_file) |
951 |
1062 |
{ |
{ |
952 |
1063 |
rg_prof_start("git_diff"); |
rg_prof_start("git_diff"); |
953 |
1064 |
//rg_log_enter("DEBUG: git_diff: a: " . rg_array2string($a)); |
//rg_log_enter("DEBUG: git_diff: a: " . rg_array2string($a)); |
954 |
1065 |
|
|
|
1066 |
|
$id = rg_xss_safe($id); |
|
1067 |
|
|
955 |
1068 |
$ret = "<div class=\"diff\">\n"; |
$ret = "<div class=\"diff\">\n"; |
956 |
1069 |
|
|
957 |
1070 |
$x = array(); |
$x = array(); |
|
... |
... |
function rg_git_diff($a, $template_file) |
964 |
1077 |
$ret .= "<br />\n"; |
$ret .= "<br />\n"; |
965 |
1078 |
|
|
966 |
1079 |
$f = rg_xss_safe($finfo['file']); |
$f = rg_xss_safe($finfo['file']); |
967 |
|
$ret .= "<a name=\"file-$f\"></a>\n"; |
|
|
1080 |
|
$ret .= '<a name="file-' . $id . '-' . $f . '"></a>' . "\n"; |
968 |
1081 |
|
|
969 |
1082 |
$ret .= "<table class=\"chunk\" summary=\"chunk\">\n"; |
$ret .= "<table class=\"chunk\" summary=\"chunk\">\n"; |
970 |
1083 |
$ret .= "<tr style=\"border: 1px; background: #dddddd\"><td colspan=\"4\">"; |
$ret .= "<tr style=\"border: 1px; background: #dddddd\"><td colspan=\"4\">"; |
|
... |
... |
function rg_git_diff($a, $template_file) |
998 |
1111 |
$ret .= " (index " . rg_xss_safe($finfo['index']) . ")"; |
$ret .= " (index " . rg_xss_safe($finfo['index']) . ")"; |
999 |
1112 |
|
|
1000 |
1113 |
// TODO: Before stats we must show commit hash, author etc. (source/log/commit/xxxxxx) |
// TODO: Before stats we must show commit hash, author etc. (source/log/commit/xxxxxx) |
1001 |
|
// TODO: what about commiter and time and rest? |
|
|
1114 |
|
// TODO: what about committer and time and rest? |
1002 |
1115 |
|
|
1003 |
1116 |
$ret .= ":"; |
$ret .= ":"; |
1004 |
1117 |
$ret .= "</td></tr>\n"; |
$ret .= "</td></tr>\n"; |
|
... |
... |
function rg_git_update_tag($db, $a) |
1177 |
1290 |
if (!empty($a['namespace'])) { |
if (!empty($a['namespace'])) { |
1178 |
1291 |
// Update the main ref (not a namespace) |
// Update the main ref (not a namespace) |
1179 |
1292 |
$reason = $a['login_username'] . ' pushed tag ' . $a['refname']; |
$reason = $a['login_username'] . ' pushed tag ' . $a['refname']; |
1180 |
|
$r = rg_git_update_ref($a['refname'], $a['old_rev'], |
|
1181 |
|
$a['new_rev'], $reason); |
|
|
1293 |
|
$r = rg_git_update_ref($a['repo_path'], $a['refname'], |
|
1294 |
|
$a['old_rev'], $a['new_rev'], $reason); |
1182 |
1295 |
if ($r !== TRUE) { |
if ($r !== TRUE) { |
1183 |
1296 |
rg_git_fatal($a['refname'] . "\nCannot update ref (" |
rg_git_fatal($a['refname'] . "\nCannot update ref (" |
1184 |
1297 |
. rg_git_error() . ")"); |
. rg_git_error() . ")"); |
|
... |
... |
function rg_git_update_tag($db, $a) |
1192 |
1305 |
} |
} |
1193 |
1306 |
|
|
1194 |
1307 |
/* |
/* |
1195 |
|
* |
|
|
1308 |
|
* Called from hooks |
1196 |
1309 |
*/ |
*/ |
1197 |
1310 |
function rg_git_update_branch($db, $a) |
function rg_git_update_branch($db, $a) |
1198 |
1311 |
{ |
{ |
|
... |
... |
function rg_git_update_branch($db, $a) |
1245 |
1358 |
$x = $_x; |
$x = $_x; |
1246 |
1359 |
$x['needed_rights'] = 'O'; |
$x['needed_rights'] = 'O'; |
1247 |
1360 |
if ((rg_rights_allow($db, $x) !== TRUE) && ($check_fast_forward == 1)) { |
if ((rg_rights_allow($db, $x) !== TRUE) && ($check_fast_forward == 1)) { |
1248 |
|
$merge_base = rg_git_merge_base($a['old_rev'], $a['new_rev']); |
|
|
1361 |
|
$merge_base = rg_git_merge_base($a['repo_path'], $a['old_rev'], |
|
1362 |
|
$a['new_rev']); |
1249 |
1363 |
if ($merge_base === FALSE) { |
if ($merge_base === FALSE) { |
1250 |
1364 |
rg_log("Error in merge_base: " . rg_git_error()); |
rg_log("Error in merge_base: " . rg_git_error()); |
1251 |
1365 |
rg_git_fatal($a['refname'] . "\nInternal error." |
rg_git_fatal($a['refname'] . "\nInternal error." |
|
... |
... |
function rg_git_update_branch($db, $a) |
1262 |
1376 |
$x = $_x; |
$x = $_x; |
1263 |
1377 |
$x['needed_rights'] = 'M'; |
$x['needed_rights'] = 'M'; |
1264 |
1378 |
if (rg_rights_allow($db, $x) !== TRUE) { |
if (rg_rights_allow($db, $x) !== TRUE) { |
1265 |
|
if (rg_git_rev_ok($a['new_rev'] . "^2")) |
|
|
1379 |
|
if (rg_git_rev_ok($a['new_rev'] . "^2") !== FALSE) |
1266 |
1380 |
rg_git_fatal($a['refname'] |
rg_git_fatal($a['refname'] |
1267 |
1381 |
. "\nYou have no rights to push merges."); |
. "\nYou have no rights to push merges."); |
1268 |
1382 |
} |
} |
|
... |
... |
function rg_git_update_branch($db, $a) |
1319 |
1433 |
} |
} |
1320 |
1434 |
|
|
1321 |
1435 |
// anonymous push - create a merge request |
// anonymous push - create a merge request |
1322 |
|
// TODO: git may fail to update the reference after this hook; |
|
1323 |
|
// the mr code should check if the update was done. |
|
1324 |
|
$mr = "refs/mr/" |
|
1325 |
|
. str_replace('refs/heads/', '', $a['refname']) |
|
1326 |
|
. "_" . str_replace('rg_', '', $a['namespace']); |
|
1327 |
|
$reason = $a['login_username'] . ' pushed a merge request' |
|
1328 |
|
. ' for ref ' . $a['refname'] |
|
1329 |
|
. ' into namespace ' . $mr; |
|
1330 |
|
$r = rg_git_update_ref($mr, "", $a['new_rev'], $reason); |
|
1331 |
|
if ($r !== TRUE) { |
|
1332 |
|
rg_log("Cannot update-ref: " . rg_git_error()); |
|
1333 |
|
rg_git_fatal($a['refname'] . ": Cannot set refs/mr/." |
|
1334 |
|
. " Try again later."); |
|
1335 |
|
} |
|
1336 |
1436 |
$ev = $a; |
$ev = $a; |
1337 |
|
$ev['category'] = 7000; |
|
|
1437 |
|
$ev['category'] = 'rg_mr_event_new'; |
1338 |
1438 |
$ev['prio'] = 100; |
$ev['prio'] = 100; |
1339 |
1439 |
$ev['ui'] = array('uid' => $a['login_uid']); |
$ev['ui'] = array('uid' => $a['login_uid']); |
1340 |
1440 |
$r = rg_event_add($db, $ev); |
$r = rg_event_add($db, $ev); |
|
... |
... |
function rg_git_update_branch($db, $a) |
1348 |
1448 |
|
|
1349 |
1449 |
$history['history_category'] = REPO_CAT_GIT_BRANCH_ANON_PUSH; |
$history['history_category'] = REPO_CAT_GIT_BRANCH_ANON_PUSH; |
1350 |
1450 |
$history['history_message'] = 'Anonymous push to ref ' |
$history['history_message'] = 'Anonymous push to ref ' |
1351 |
|
. $a['refname'] . ' into namespace ' . $mr; |
|
|
1451 |
|
. $a['refname'] . ' into namespace ' . $a['namespace']; |
1352 |
1452 |
} else { |
} else { |
1353 |
1453 |
rg_log("DEBUG: We are allowed to push."); |
rg_log("DEBUG: We are allowed to push."); |
1354 |
1454 |
|
|
|
... |
... |
function rg_git_update_branch($db, $a) |
1358 |
1458 |
// Updating main ref (not a namespace) |
// Updating main ref (not a namespace) |
1359 |
1459 |
$reason = $a['login_username'] |
$reason = $a['login_username'] |
1360 |
1460 |
. ' pushed ref ' . $a['refname']; |
. ' pushed ref ' . $a['refname']; |
1361 |
|
$r = rg_git_update_ref($a['refname'], $a['old_rev'], |
|
1362 |
|
$a['new_rev'], $reason); |
|
|
1461 |
|
$r = rg_git_update_ref($a['repo_path'], $a['refname'], |
|
1462 |
|
$a['old_rev'], $a['new_rev'], $reason); |
1363 |
1463 |
if ($r !== TRUE) { |
if ($r !== TRUE) { |
1364 |
1464 |
rg_git_fatal($a['refname'] |
rg_git_fatal($a['refname'] |
1365 |
1465 |
. "\nCannot update ref (" |
. "\nCannot update ref (" |
|
... |
... |
function rg_git_content_by_file($treeish, $file) |
1586 |
1686 |
function rg_git_log2listing($log, $rg, $commit_table) |
function rg_git_log2listing($log, $rg, $commit_table) |
1587 |
1687 |
{ |
{ |
1588 |
1688 |
if ($log === FALSE) |
if ($log === FALSE) |
1589 |
|
return rg_template('repo/not_init.html', $rg, TRUE /* xss */); |
|
|
1689 |
|
return rg_template('repo/not_init.html', $rg, TRUE/*xss*/); |
1590 |
1690 |
|
|
1591 |
1691 |
$ret = ''; |
$ret = ''; |
1592 |
1692 |
|
|
|
... |
... |
function rg_git_log2listing($log, $rg, $commit_table) |
1595 |
1695 |
// Set 'url' |
// Set 'url' |
1596 |
1696 |
foreach ($log as $index => $i) |
foreach ($log as $index => $i) |
1597 |
1697 |
$log[$index]['vars']['commit_url'] = |
$log[$index]['vars']['commit_url'] = |
1598 |
|
rg_xss_safe($rg['mr']) |
|
1599 |
|
. "#sha1-" . rg_xss_safe($i['vars']['sha1_short']); |
|
|
1698 |
|
rg_xss_safe($rg['mr']['id']) |
|
1699 |
|
. "#sha1-" . rg_xss_safe($i['vars']['sha1']); |
1600 |
1700 |
$ret .= rg_git_log_template($log, 'repo/log', $rg); |
$ret .= rg_git_log_template($log, 'repo/log', $rg); |
1601 |
1701 |
} |
} |
1602 |
1702 |
|
|
1603 |
1703 |
// TODO: move this into a template! |
// TODO: move this into a template! |
|
1704 |
|
$ret .= '<div style="margin-top: 8pt; margin-left: 8pt">' . "\n"; |
1604 |
1705 |
foreach ($log as $junk => $i) { |
foreach ($log as $junk => $i) { |
|
1706 |
|
//rg_log_ml('DEBUG: i=' . print_r($i, TRUE)); |
|
1707 |
|
|
1605 |
1708 |
// Some info about commit |
// Some info about commit |
1606 |
|
$ret .= "<br /><b>" |
|
1607 |
|
. "<a name=\"sha1-" . rg_xss_safe($i['vars']['sha1_short']) . "\">" |
|
1608 |
|
. "Commit " . rg_xss_safe($i['vars']['sha1_short']) |
|
|
1709 |
|
$ret .= "<b>" |
|
1710 |
|
. "<a name=\"sha1-" . rg_xss_safe($i['vars']['sha1']) . "\">" |
|
1711 |
|
. "Commit " . rg_xss_safe($i['vars']['sha1']) |
1609 |
1712 |
. "</a></b> - " . rg_xss_safe($i['vars']['subject']) . "\n"; |
. "</a></b> - " . rg_xss_safe($i['vars']['subject']) . "\n"; |
1610 |
1713 |
|
|
1611 |
1714 |
if (!empty($i['vars']['body'])) |
if (!empty($i['vars']['body'])) |
1612 |
1715 |
$ret .= "<br />\n" |
$ret .= "<br />\n" |
1613 |
1716 |
. nl2br(rg_xss_safe($i['vars']['body'])); |
. nl2br(rg_xss_safe($i['vars']['body'])); |
1614 |
1717 |
|
|
1615 |
|
$ret .= "<br />\n" |
|
1616 |
|
. "<b>Author</b>: " . rg_xss_safe($i['vars']['author name']); |
|
|
1718 |
|
$ret .= "<br /><b>Author</b>: " . rg_xss_safe($i['vars']['author name']); |
1617 |
1719 |
|
|
1618 |
|
if (!empty($i['vars']['commiter name'])) |
|
1619 |
|
$ret .= "<br />\n" |
|
1620 |
|
. "<b>Commiter</b>: " . rg_xss_safe($i['vars']['commiter name']); |
|
|
1720 |
|
$ret .= "<br /><b>Author date (UTC)</b>: " |
|
1721 |
|
. gmdate("Y-m-d H:i", $i['vars']['author date']); |
1621 |
1722 |
|
|
1622 |
|
$ret .= "<br />\n" |
|
1623 |
|
. "<b>Date (UTC)</b>: " . gmdate("Y-m-d H:i", $i['vars']['author date']); |
|
1624 |
|
$ret .= "<br />\n"; |
|
|
1723 |
|
if (!empty($i['vars']['committer name'])) |
|
1724 |
|
$ret .= "<br /><b>Committer</b>: " |
|
1725 |
|
. rg_xss_safe($i['vars']['committer name']); |
|
1726 |
|
|
|
1727 |
|
$ret .= '<br /><b>Commit date (UTC)</b>: ' |
|
1728 |
|
. gmdate("Y-m-d H:i", $i['vars']['committer date']); |
|
1729 |
|
|
|
1730 |
|
$ret .= '<br /><b>Tree</b>: ' . $i['vars']['tree']; |
|
1731 |
|
|
|
1732 |
|
if (!empty($i['vars']['parents'])) |
|
1733 |
|
$ret .= '<br /><b>Parents</b>: ' |
|
1734 |
|
. $i['vars']['parents']; |
|
1735 |
|
|
|
1736 |
|
if (!empty($i['vars']['sign_key'])) |
|
1737 |
|
$ret .= '<br /><b>Signing key</b>: ' |
|
1738 |
|
. $i['vars']['sign_key']; |
1625 |
1739 |
|
|
1626 |
1740 |
// stats |
// stats |
1627 |
1741 |
$r = rg_git_files_stats($i['files'], 'repo/fstat'); |
$r = rg_git_files_stats($i['files'], 'repo/fstat'); |
|
... |
... |
function rg_git_log2listing($log, $rg, $commit_table) |
1631 |
1745 |
|
|
1632 |
1746 |
// diff |
// diff |
1633 |
1747 |
//rg_log_ml("DEBUG: i[files]=" . print_r($i['files'], TRUE)); |
//rg_log_ml("DEBUG: i[files]=" . print_r($i['files'], TRUE)); |
1634 |
|
$r = rg_git_diff($i['files'], 'repo/diff.html'); |
|
|
1748 |
|
$r = rg_git_diff($i['vars']['sha1'], $i['files'], |
|
1749 |
|
'repo/diff.html'); |
1635 |
1750 |
if ($r === FALSE) |
if ($r === FALSE) |
1636 |
1751 |
return "Internal error"; |
return "Internal error"; |
1637 |
1752 |
$ret .= $r; |
$ret .= $r; |
1638 |
1753 |
} |
} |
|
1754 |
|
$ret .= '</div>' . "\n"; |
1639 |
1755 |
|
|
1640 |
1756 |
return $ret; |
return $ret; |
1641 |
1757 |
} |
} |
|
... |
... |
function rg_git_archive($repo_path, $treeish, $archive_name, $format) |
1673 |
1789 |
return $ret; |
return $ret; |
1674 |
1790 |
} |
} |
1675 |
1791 |
|
|
|
1792 |
|
/* |
|
1793 |
|
* Tests if a merge will result in conflicts |
|
1794 |
|
****************** Example for conflict: |
|
1795 |
|
* changed in both |
|
1796 |
|
* base 100644 72943a16fb2c8f38f9dde202b7a70ccc19c52f34 a |
|
1797 |
|
* our 100644 959479a9d0d05bf843067e5f9fb4b2abef354f70 a |
|
1798 |
|
* their 100644 dbee0265d31298531773537e6e37e4fd1ee71d62 a |
|
1799 |
|
* @@ -1,2 +1,6 @@ |
|
1800 |
|
* aaa |
|
1801 |
|
* +<<<<<<< .our |
|
1802 |
|
* ccc |
|
1803 |
|
* +======= |
|
1804 |
|
* +bbb |
|
1805 |
|
* +>>>>>>> .their |
|
1806 |
|
* |
|
1807 |
|
****************** Example for a merge without conflicts: |
|
1808 |
|
* merged |
|
1809 |
|
* result 100644 3c5556ce5ed90f293dd05e5942ccdbff43a71556 a |
|
1810 |
|
* our 100644 959479a9d0d05bf843067e5f9fb4b2abef354f70 a |
|
1811 |
|
* @@ -1,2 +1,2 @@ |
|
1812 |
|
* aaa |
|
1813 |
|
* -ccc |
|
1814 |
|
* +ddd |
|
1815 |
|
*/ |
|
1816 |
|
function rg_git_merge_tree($repo_path, $base, $a, $b) |
|
1817 |
|
{ |
|
1818 |
|
global $rg_git_zero; |
|
1819 |
|
global $rg_git_empty; |
|
1820 |
|
|
|
1821 |
|
rg_prof_start('git_merge_tree'); |
|
1822 |
|
rg_log_enter('rg_git_merge_tree base=' |
|
1823 |
|
. $base . ' a=' . $a . ' b=' . $b); |
|
1824 |
|
|
|
1825 |
|
$ret = FALSE; |
|
1826 |
|
while (1) { |
|
1827 |
|
$head = rg_git_load_ref($repo_path, $a); |
|
1828 |
|
if ($head === FALSE) |
|
1829 |
|
break; |
|
1830 |
|
$key = 'git' |
|
1831 |
|
. '::' . sha1($repo_path) |
|
1832 |
|
. '::' . 'merge-tree' |
|
1833 |
|
. '::' . $head . '::' . $b; |
|
1834 |
|
$r = rg_cache_get($key); |
|
1835 |
|
if ($r !== FALSE) { |
|
1836 |
|
$ret = $r; |
|
1837 |
|
break; |
|
1838 |
|
} |
|
1839 |
|
|
|
1840 |
|
$cmd = 'git --git-dir=' . escapeshellarg($repo_path) |
|
1841 |
|
. ' merge-tree' |
|
1842 |
|
. ' ' . escapeshellarg($base) |
|
1843 |
|
. ' ' . escapeshellarg($a) |
|
1844 |
|
. ' ' . escapeshellarg($b); |
|
1845 |
|
$a = rg_exec($cmd); |
|
1846 |
|
if ($a['ok'] != 1) { |
|
1847 |
|
rg_git_set_error('error on git merge-tree (' |
|
1848 |
|
. $a['errmsg'] . ')'); |
|
1849 |
|
break; |
|
1850 |
|
} |
|
1851 |
|
|
|
1852 |
|
$ret = trim($a['data']); |
|
1853 |
|
rg_cache_set($key, $ret, RG_SOCKET_NO_WAIT); |
|
1854 |
|
rg_log_ml('DEBUG: merge-tree: ' . $ret); |
|
1855 |
|
break; |
|
1856 |
|
} |
|
1857 |
|
|
|
1858 |
|
rg_log_exit(); |
|
1859 |
|
rg_prof_end('git_merge_tree'); |
|
1860 |
|
return $ret; |
|
1861 |
|
} |
|
1862 |
|
|
|
1863 |
|
function rg_git_merge_tree_html($repo_path, $base, $a, $b) |
|
1864 |
|
{ |
|
1865 |
|
$r = rg_git_merge_tree($repo_path, $base, $a, $b); |
|
1866 |
|
if ($r === FALSE) |
|
1867 |
|
return rg_git_error(); |
|
1868 |
|
|
|
1869 |
|
return nl2br(rg_xss_safe($r)); |
|
1870 |
|
} |
|
1871 |
|
|
|
1872 |
|
/* |
|
1873 |
|
* Returns the status of a pull request |
|
1874 |
|
* Returns FALSE on error, 1 if merge is without conflict, else 0 |
|
1875 |
|
*/ |
|
1876 |
|
function rg_git_merge_without_conflict($repo_path, $a, $b) |
|
1877 |
|
{ |
|
1878 |
|
rg_log_enter('git_merge_without_conflict a=' . $a . ' b=' . $b); |
|
1879 |
|
|
|
1880 |
|
$ret = FALSE; |
|
1881 |
|
while (1) { |
|
1882 |
|
$base = rg_git_merge_base($repo_path, $a, $b); |
|
1883 |
|
if ($base === FALSE) |
|
1884 |
|
break; |
|
1885 |
|
|
|
1886 |
|
$out = rg_git_merge_tree($repo_path, $base, $a, $b); |
|
1887 |
|
if($out === FALSE) |
|
1888 |
|
break; |
|
1889 |
|
|
|
1890 |
|
$r = strstr($out, "\n+<<<<<<<"); |
|
1891 |
|
if ($r === FALSE) { |
|
1892 |
|
$ret = 1; |
|
1893 |
|
break; |
|
1894 |
|
} |
|
1895 |
|
|
|
1896 |
|
$ret = 0; |
|
1897 |
|
break; |
|
1898 |
|
} |
|
1899 |
|
|
|
1900 |
|
rg_log_exit(); |
|
1901 |
|
return $ret; |
|
1902 |
|
} |
|
1903 |
|
|
|
1904 |
|
/* |
|
1905 |
|
* Do a merge |
|
1906 |
|
* @ff - 0 = no fast-forward, 1 = fast-forward allowed |
|
1907 |
|
* @msg - merge message |
|
1908 |
|
* Returns the output of the command or FALSE |
|
1909 |
|
*/ |
|
1910 |
|
function rg_git_merge($repo_path, $a, $b, $ff, $msg) |
|
1911 |
|
{ |
|
1912 |
|
global $rg_git_zero; |
|
1913 |
|
global $rg_git_empty; |
|
1914 |
|
|
|
1915 |
|
rg_prof_start('git_merge'); |
|
1916 |
|
rg_log_enter('git_merge' . ' a=' . $a . ' b=' . $b . ' ff=' . $ff |
|
1917 |
|
. ' msg=' . $msg); |
|
1918 |
|
|
|
1919 |
|
$ret = FALSE; |
|
1920 |
|
while (1) { |
|
1921 |
|
if (empty($repo_path)) |
|
1922 |
|
$add = ''; |
|
1923 |
|
else |
|
1924 |
|
$add = ' --git-dir=' . escapeshellarg($repo_path); |
|
1925 |
|
|
|
1926 |
|
$work_tree = rg_tmp_path('git_merge_' . rg_id(10)); |
|
1927 |
|
$r = @mkdir($work_tree, 0700, TRUE); |
|
1928 |
|
if ($r !== TRUE) { |
|
1929 |
|
rg_git_set_error('cannot create temporary dir for merge'); |
|
1930 |
|
break; |
|
1931 |
|
} |
|
1932 |
|
$add .= ' --work-tree ' . escapeshellarg($work_tree); |
|
1933 |
|
|
|
1934 |
|
if ($ff == 1) |
|
1935 |
|
$add_ff = ' --ff'; |
|
1936 |
|
else |
|
1937 |
|
$add_ff = ' --no-ff'; |
|
1938 |
|
|
|
1939 |
|
$cmd = 'git' |
|
1940 |
|
. $add |
|
1941 |
|
. ' merge' |
|
1942 |
|
. $add_ff |
|
1943 |
|
. ' --stat' |
|
1944 |
|
. ' -m ' . escapeshellarg($msg) |
|
1945 |
|
. ' ' . escapeshellarg($a) |
|
1946 |
|
. ' ' . escapeshellarg($b); |
|
1947 |
|
$a = rg_exec($cmd); |
|
1948 |
|
rg_rmdir($work_tree); |
|
1949 |
|
if ($a['ok'] != 1) { |
|
1950 |
|
rg_git_set_error('error on git merge (' |
|
1951 |
|
. $a['errmsg'] . ')'); |
|
1952 |
|
break; |
|
1953 |
|
} |
|
1954 |
|
|
|
1955 |
|
$ret = trim($a['data']); |
|
1956 |
|
break; |
|
1957 |
|
} |
|
1958 |
|
|
|
1959 |
|
rg_log_exit(); |
|
1960 |
|
rg_prof_end('git_merge'); |
|
1961 |
|
return $ret; |
|
1962 |
|
} |
|
1963 |
|
|
|
1964 |
|
/* |
|
1965 |
|
* Creates a pull request against a user repo to be sent by e-mail |
|
1966 |
|
*/ |
|
1967 |
|
function rg_git_request_pull($repo_path, $start, $url, $end, $patch) |
|
1968 |
|
{ |
|
1969 |
|
global $rg_git_zero; |
|
1970 |
|
global $rg_git_empty; |
|
1971 |
|
|
|
1972 |
|
rg_prof_start('git_request_pull'); |
|
1973 |
|
rg_log_enter('git_request_pull' . ' start=' . $start |
|
1974 |
|
. ' url=' . $url . ' end=' . $end |
|
1975 |
|
. ' patch=' . ($patch ? 'yes' : 'no')); |
|
1976 |
|
|
|
1977 |
|
$text = ''; |
|
1978 |
|
$ret = FALSE; |
|
1979 |
|
while (1) { |
|
1980 |
|
$rg['req'] = array(); |
|
1981 |
|
$rg['req']['start'] = $start; |
|
1982 |
|
$rg['req']['url'] = $url; |
|
1983 |
|
$rg['req']['end'] = $end; |
|
1984 |
|
|
|
1985 |
|
$text .= rg_template('repo/mr/req-pull.txt', $rg, TRUE/*xss*/); |
|
1986 |
|
|
|
1987 |
|
$r = rg_git_shortlog($repo_path, $baserev, $headrev); |
|
1988 |
|
if ($r === FALSE) |
|
1989 |
|
break; |
|
1990 |
|
$text .= $r; |
|
1991 |
|
|
|
1992 |
|
$cmd = 'git diff -M --stat --summary'; |
|
1993 |
|
if ($patch) |
|
1994 |
|
$cmd .= ' --patch'; |
|
1995 |
|
$cmd .= escapeshellarg($start) . '..' . escapeshellarg($end); |
|
1996 |
|
$r = rg_exec($cmd); |
|
1997 |
|
if ($a['ok'] != 1) { |
|
1998 |
|
rg_git_set_error('error on git diff: ' . $a['errmsg']); |
|
1999 |
|
break; |
|
2000 |
|
} |
|
2001 |
|
$text .= $r['data']; |
|
2002 |
|
|
|
2003 |
|
$ret = $text; |
|
2004 |
|
break; |
|
2005 |
|
} |
|
2006 |
|
|
|
2007 |
|
rg_log_exit(); |
|
2008 |
|
rg_prof_end('git_pull_request'); |
|
2009 |
|
return $ret; |
|
2010 |
|
} |
|
2011 |
|
|
1676 |
2012 |
?> |
?> |
File inc/mr.inc.php changed (mode: 100644) (index 399e80a..3c8ed10) |
3 |
3 |
|
|
4 |
4 |
require_once($INC . "/util.inc.php"); |
require_once($INC . "/util.inc.php"); |
5 |
5 |
require_once($INC . "/sql.inc.php"); |
require_once($INC . "/sql.inc.php"); |
|
6 |
|
require_once($INC . '/user.inc.php'); |
6 |
7 |
require_once($INC . "/events.inc.php"); |
require_once($INC . "/events.inc.php"); |
7 |
8 |
|
|
8 |
9 |
$rg_mr_env_q = getenv("ROCKETGIT_MR_QUEUE"); |
$rg_mr_env_q = getenv("ROCKETGIT_MR_QUEUE"); |
|
... |
... |
function rg_mr_error() |
26 |
27 |
return $rg_mr_error; |
return $rg_mr_error; |
27 |
28 |
} |
} |
28 |
29 |
|
|
|
30 |
|
|
29 |
31 |
/* |
/* |
30 |
|
* Events functions |
|
|
32 |
|
* Event functions |
31 |
33 |
*/ |
*/ |
32 |
34 |
$rg_mr_functions = array( |
$rg_mr_functions = array( |
33 |
|
7000 => 'rg_mr_event_new', |
|
34 |
|
7001 => 'rg_mr_event_add_to_db' |
|
|
35 |
|
'rg_mr_event_new' => 'rg_mr_event_new', |
|
36 |
|
'rg_mr_event_add_to_db' => 'rg_mr_event_add_to_db', |
|
37 |
|
'mr_merge' => 'rg_mr_event_merge' |
35 |
38 |
); |
); |
36 |
39 |
rg_event_register_functions($rg_mr_functions); |
rg_event_register_functions($rg_mr_functions); |
37 |
40 |
|
|
|
41 |
|
/* |
|
42 |
|
* This is called when the user press "Merge" button |
|
43 |
|
*/ |
|
44 |
|
function rg_mr_event_merge($db, $ev) |
|
45 |
|
{ |
|
46 |
|
$ret = array(); |
|
47 |
|
|
|
48 |
|
// TODO: we should send the error messages only at last try! Anywhere! Really?! |
|
49 |
|
// TODO: care! we should not send the mail before doing the merge! |
|
50 |
|
// TODO: check also all the other events. |
|
51 |
|
// do the merge |
|
52 |
|
|
|
53 |
|
$r = rg_git_merge($ev['repo_path'], $ev['merge_against'], |
|
54 |
|
$ev['mri']['new_rev'], $ev['merge_ff'], $ev['merge_msg']); |
|
55 |
|
if ($r === FALSE) { |
|
56 |
|
rg_log('Merge failed: ' . rg_git_error()); |
|
57 |
|
// TODO: notify ui['uid'] that the merge failed |
|
58 |
|
rg_mail_template('repo/mail/merge_failed', $ev); |
|
59 |
|
return $ret; |
|
60 |
|
} |
|
61 |
|
|
|
62 |
|
$r = rg_mr_merge_set_status($db, $ev['ri']['repo_id'], |
|
63 |
|
$ev['mri']['id'], time()); |
|
64 |
|
if ($r === FALSE) |
|
65 |
|
return FALSE; |
|
66 |
|
|
|
67 |
|
// notify the requester (if not anonymous) |
|
68 |
|
// TODO: notify the watchers? |
|
69 |
|
// TODO: notify the users who commented on the pull request? |
|
70 |
|
// TODO: notify users who watch the pull request? |
|
71 |
|
|
|
72 |
|
return $ret; |
|
73 |
|
} |
|
74 |
|
|
38 |
75 |
/* |
/* |
39 |
76 |
* This is called when a new pull request is done |
* This is called when a new pull request is done |
40 |
77 |
*/ |
*/ |
|
... |
... |
function rg_mr_event_new($db, $ev) |
44 |
81 |
|
|
45 |
82 |
// Insert it into database |
// Insert it into database |
46 |
83 |
$ret[] = array_merge($ev, |
$ret[] = array_merge($ev, |
47 |
|
array('category' => 7001, 'prio' => 100)); |
|
|
84 |
|
array('category' => 'rg_mr_event_add_to_db', 'prio' => 100)); |
48 |
85 |
|
|
49 |
86 |
// TODO: Notify admins of the repo |
// TODO: Notify admins of the repo |
50 |
87 |
|
|
|
... |
... |
function rg_mr_event_new($db, $ev) |
59 |
96 |
function rg_mr_event_add_to_db($db, $a) |
function rg_mr_event_add_to_db($db, $a) |
60 |
97 |
{ |
{ |
61 |
98 |
rg_prof_start('mr_event_add_to_db'); |
rg_prof_start('mr_event_add_to_db'); |
62 |
|
rg_log_start('mr_add_to_db: a: ' . rg_array2string($a)); |
|
|
99 |
|
rg_log_enter('mr_add_to_db: a: ' . rg_array2string($a)); |
63 |
100 |
|
|
64 |
101 |
$now = time(); |
$now = time(); |
65 |
102 |
|
|
|
... |
... |
function rg_mr_event_add_to_db($db, $a) |
67 |
104 |
$rollback = 0; |
$rollback = 0; |
68 |
105 |
while (1) { |
while (1) { |
69 |
106 |
if (rg_sql_begin($db) !== TRUE) { |
if (rg_sql_begin($db) !== TRUE) { |
70 |
|
rg_mr_set_error('start tranzaction failed'); |
|
|
107 |
|
rg_mr_set_error('start transaction failed'); |
71 |
108 |
break; |
break; |
72 |
109 |
} |
} |
73 |
110 |
|
|
|
... |
... |
function rg_mr_event_add_to_db($db, $a) |
79 |
116 |
break; |
break; |
80 |
117 |
} |
} |
81 |
118 |
|
|
|
119 |
|
// TODO: git may fail to update the reference after this hook; |
|
120 |
|
// the mr code should check if the update was done. |
|
121 |
|
$mr = 'refs/mr/' . $id; |
|
122 |
|
$reason = $a['login_username'] . ' pushed a merge request' |
|
123 |
|
. ' for ref ' . $a['refname'] |
|
124 |
|
. ' into ' . $mr; |
|
125 |
|
$r = rg_git_update_ref($a['repo_path'], $mr, '', $a['new_rev'], $reason); |
|
126 |
|
if ($r !== TRUE) { |
|
127 |
|
rg_mr_set_error('cannot update-ref: ' . rg_git_error()); |
|
128 |
|
break; |
|
129 |
|
} |
|
130 |
|
|
82 |
131 |
$a['id'] = $id; |
$a['id'] = $id; |
|
132 |
|
$a['who'] = $a['ui']['uid']; |
83 |
133 |
$sql = 'INSERT INTO merge_requests (repo_id, id, itime' |
$sql = 'INSERT INTO merge_requests (repo_id, id, itime' |
84 |
|
. ', namespace, refname, old_rev, new_rev, done, ip)' |
|
|
134 |
|
. ', namespace, refname, old_rev, new_rev, done, ip' |
|
135 |
|
. ', who)' |
85 |
136 |
. ' VALUES (@@repo_id@@, @@id@@, @@itime@@' |
. ' VALUES (@@repo_id@@, @@id@@, @@itime@@' |
86 |
137 |
. ', @@namespace@@, @@refname@@, @@old_rev@@' |
. ', @@namespace@@, @@refname@@, @@old_rev@@' |
87 |
|
. ', @@new_rev@@, 0, @@ip@@)'; |
|
|
138 |
|
. ', @@new_rev@@, 0, @@ip@@, @@who@@)'; |
88 |
139 |
$res = rg_sql_query_params($db, $sql, $a); |
$res = rg_sql_query_params($db, $sql, $a); |
89 |
140 |
if ($res === FALSE) { |
if ($res === FALSE) { |
90 |
141 |
rg_mr_set_error('cannot insert merge request'); |
rg_mr_set_error('cannot insert merge request'); |
|
... |
... |
function rg_mr_queue_process($db) |
185 |
236 |
/* |
/* |
186 |
237 |
* Helper to cosmetic mr data |
* Helper to cosmetic mr data |
187 |
238 |
*/ |
*/ |
188 |
|
function rg_mr_cosmetic(&$row) |
|
|
239 |
|
function rg_mr_cosmetic($db, &$row) |
189 |
240 |
{ |
{ |
190 |
241 |
$row['date_utc'] = gmdate("Y-m-d H:i", $row['itime']); |
$row['date_utc'] = gmdate("Y-m-d H:i", $row['itime']); |
191 |
242 |
$row['old_rev_short'] = substr($row['old_rev'], 0, 7); |
$row['old_rev_short'] = substr($row['old_rev'], 0, 7); |
192 |
243 |
$row['new_rev_short'] = substr($row['new_rev'], 0, 7); |
$row['new_rev_short'] = substr($row['new_rev'], 0, 7); |
|
244 |
|
|
|
245 |
|
if (!isset($row['who_nice'])) { |
|
246 |
|
if ($row['who'] == 0) { |
|
247 |
|
$row['who_nice'] = 'anonymous'; |
|
248 |
|
} else { |
|
249 |
|
$ui = rg_user_info($db, $row['who'], '', ''); |
|
250 |
|
if ($ui['exists'] == 1) |
|
251 |
|
$row['who_nice'] = $ui['username']; |
|
252 |
|
else |
|
253 |
|
$row['who_nice'] = 'n/a'; |
|
254 |
|
} |
|
255 |
|
} |
|
256 |
|
$row['done_nice'] = gmdate("Y-m-d H:i", $row['done']); |
193 |
257 |
} |
} |
194 |
258 |
|
|
195 |
259 |
/* |
/* |
196 |
260 |
* Loads merge requests |
* Loads merge requests |
|
261 |
|
* @type - 'pending' or 'closed' |
197 |
262 |
* @limit = 0 => no limit |
* @limit = 0 => no limit |
198 |
263 |
*/ |
*/ |
199 |
|
function rg_mr_load($db, $repo_id, $limit) |
|
|
264 |
|
function rg_mr_load($db, $repo_id, $type, $limit) |
200 |
265 |
{ |
{ |
201 |
|
rg_log("mr_load: repo_id=$repo_id limit=$limit"); |
|
|
266 |
|
rg_log("mr_load: repo_id=$repo_id type=$type limit=$limit"); |
|
267 |
|
|
|
268 |
|
if (strcmp($type, 'pending') == 0) |
|
269 |
|
$add = ' AND done = 0'; |
|
270 |
|
else |
|
271 |
|
$add = ' AND done > 1000'; // first values are for different status |
202 |
272 |
|
|
203 |
|
$params = array("repo_id" => $repo_id); |
|
204 |
|
$sql = "SELECT * FROM merge_requests" |
|
205 |
|
. " WHERE repo_id = @@repo_id@@" |
|
206 |
|
. " AND done = 0" |
|
207 |
|
. " ORDER BY itime"; |
|
|
273 |
|
$params = array('repo_id' => $repo_id); |
|
274 |
|
$sql = 'SELECT * FROM merge_requests' |
|
275 |
|
. ' WHERE repo_id = @@repo_id@@' |
|
276 |
|
. $add |
|
277 |
|
. ' ORDER BY itime'; |
208 |
278 |
if ($limit > 0) |
if ($limit > 0) |
209 |
|
$sql .= " LIMIT " . $limit; |
|
|
279 |
|
$sql .= ' LIMIT ' . $limit; |
210 |
280 |
$res = rg_sql_query_params($db, $sql, $params); |
$res = rg_sql_query_params($db, $sql, $params); |
211 |
281 |
if ($res === FALSE) { |
if ($res === FALSE) { |
212 |
282 |
rg_mr_set_error("Cannot load merge requests (" . rg_sql_error() . ")"); |
rg_mr_set_error("Cannot load merge requests (" . rg_sql_error() . ")"); |
|
... |
... |
function rg_mr_load($db, $repo_id, $limit) |
215 |
285 |
|
|
216 |
286 |
$ret = array(); |
$ret = array(); |
217 |
287 |
while (($row = rg_sql_fetch_array($res))) { |
while (($row = rg_sql_fetch_array($res))) { |
218 |
|
rg_mr_cosmetic($row); |
|
|
288 |
|
rg_mr_cosmetic($db, $row); |
219 |
289 |
$ret[] = $row; |
$ret[] = $row; |
220 |
290 |
} |
} |
221 |
291 |
rg_sql_free_result($res); |
rg_sql_free_result($res); |
|
... |
... |
function rg_mr_load_one($db, $repo_id, $id) |
242 |
312 |
} |
} |
243 |
313 |
|
|
244 |
314 |
$row = rg_sql_fetch_array($res); |
$row = rg_sql_fetch_array($res); |
245 |
|
rg_mr_cosmetic($row); |
|
|
315 |
|
rg_mr_cosmetic($db, $row); |
246 |
316 |
|
|
247 |
317 |
rg_sql_free_result($res); |
rg_sql_free_result($res); |
248 |
318 |
|
|
|
... |
... |
function rg_mr_load_one($db, $repo_id, $id) |
250 |
320 |
return $row; |
return $row; |
251 |
321 |
} |
} |
252 |
322 |
|
|
|
323 |
|
/* |
|
324 |
|
* Sets the status ('done' filed of a merge request |
|
325 |
|
* @status - 0 - not merged, > 10 = timestamp when the merge took place |
|
326 |
|
*/ |
|
327 |
|
function rg_mr_merge_set_status($db, $repo_id, $id, $status) |
|
328 |
|
{ |
|
329 |
|
$ret = FALSE; |
|
330 |
|
while (1) { |
|
331 |
|
$params = array('repo_id' => $repo_id, |
|
332 |
|
'id' => $id, |
|
333 |
|
'status' => $status |
|
334 |
|
); |
|
335 |
|
$sql = 'UPDATE merge_requests' |
|
336 |
|
. ' SET done = @@status@@' |
|
337 |
|
. ' WHERE repo_id = @@repo_id@@' |
|
338 |
|
. ' AND id = @@id@@'; |
|
339 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
340 |
|
if ($res === FALSE) { |
|
341 |
|
rg_mr_set_error('cannot update status (' . rg_sql_error()); |
|
342 |
|
break; |
|
343 |
|
} |
|
344 |
|
rg_sql_free_result($res); |
|
345 |
|
|
|
346 |
|
$ret = TRUE; |
|
347 |
|
break; |
|
348 |
|
} |
|
349 |
|
|
|
350 |
|
return $ret; |
|
351 |
|
} |
|
352 |
|
|
|
353 |
|
/* |
|
354 |
|
* High level merge request function |
|
355 |
|
*/ |
|
356 |
|
function rg_mr_high_level($db, &$rg, $paras) |
|
357 |
|
{ |
|
358 |
|
rg_prof_start('mr_high_level'); |
|
359 |
|
rg_log_enter('mr_high_level'); |
|
360 |
|
|
|
361 |
|
$ret = ''; |
|
362 |
|
while (1) { |
|
363 |
|
if ($rg['ri']['git_dir_done'] == 0) { |
|
364 |
|
$ret .= rg_template('repo/no_git_dir.html', |
|
365 |
|
$rg, TRUE /*xss*/); |
|
366 |
|
break; |
|
367 |
|
} |
|
368 |
|
|
|
369 |
|
// TODO: mrs.html is empty! |
|
370 |
|
$ret .= rg_template('repo/mrs.html', $rg, TRUE /*xss*/); |
|
371 |
|
|
|
372 |
|
$op = array_shift($paras); |
|
373 |
|
if (empty($op)) { |
|
374 |
|
$op = 'pending'; |
|
375 |
|
} else { |
|
376 |
|
$mr = sprintf('%u', $op); |
|
377 |
|
if ($mr > 0) |
|
378 |
|
$op = ''; |
|
379 |
|
} |
|
380 |
|
|
|
381 |
|
rg_log('DEBUG: op=' . $op); |
|
382 |
|
$rg['menu']['mr'][$op] = 1; |
|
383 |
|
$rg['HTML:menu_repo_level2'] = |
|
384 |
|
rg_template('repo/mr/menu.html', $rg, TRUE /*xss*/); |
|
385 |
|
|
|
386 |
|
if ((strcmp($op, 'pending') == 0) || (strcmp($op, 'closed') == 0)) { |
|
387 |
|
$rg['mr']['op'] = $op; |
|
388 |
|
$r = rg_mr_load($db, $rg['ri']['repo_id'], $op, |
|
389 |
|
0 /*no limit*/); |
|
390 |
|
if ($r === FALSE) { |
|
391 |
|
$ret .= 'error getting merge request list (' |
|
392 |
|
. rg_mr_error() . ')'; |
|
393 |
|
} else { |
|
394 |
|
$ret .= rg_template_table('repo/mr/list', $r, $rg); |
|
395 |
|
} |
|
396 |
|
break; |
|
397 |
|
} else if (strcmp($op, 'create') == 0) { |
|
398 |
|
$ret .= rg_warning('not yet implemented'); |
|
399 |
|
break; |
|
400 |
|
} |
|
401 |
|
|
|
402 |
|
$mri = rg_mr_load_one($db, $rg['ri']['repo_id'], $mr); |
|
403 |
|
if ($mri === FALSE) { |
|
404 |
|
$ret .= 'error loading merge request' |
|
405 |
|
. ' (' . rg_mr_error() . ')'; |
|
406 |
|
break; |
|
407 |
|
} |
|
408 |
|
|
|
409 |
|
$mri['merge_in_progress'] = 0; |
|
410 |
|
$mri['already_merged'] = 0; |
|
411 |
|
$against = rg_git_short($mri['refname']); |
|
412 |
|
|
|
413 |
|
$mr_op = array_shift($paras); |
|
414 |
|
rg_log('DEBUG: mr_op=' . $mr_op); |
|
415 |
|
if (strcmp($mr_op, 'merge') == 0) { |
|
416 |
|
if ($rg['can_admin'] !== 1) { |
|
417 |
|
$ret .= rg_warning('Not allowed!'); |
|
418 |
|
break; |
|
419 |
|
} |
|
420 |
|
|
|
421 |
|
if (!rg_valid_referer()) { |
|
422 |
|
$ret .= rg_warning('Invalid referer; try again.'); |
|
423 |
|
break; |
|
424 |
|
} |
|
425 |
|
|
|
426 |
|
if (!rg_token_valid($db, $rg, 'mr_merge', FALSE)) { |
|
427 |
|
$ret .= rg_warning('Invalid token; try again.'); |
|
428 |
|
break; |
|
429 |
|
} |
|
430 |
|
|
|
431 |
|
$event = array( |
|
432 |
|
'category' => 'mr_merge', |
|
433 |
|
'prio' => 30, |
|
434 |
|
'ri' => $rg['ri'], |
|
435 |
|
'ui' => $rg['login_ui'], |
|
436 |
|
'repo_path' => $rg['repo_path'], |
|
437 |
|
'mri' => $mri, |
|
438 |
|
'merge_against' => $against, |
|
439 |
|
'merge_ff' => rg_var_uint('merge_ff'), |
|
440 |
|
'merge_msg' => rg_var_str('merge_msg') |
|
441 |
|
); |
|
442 |
|
$r = rg_event_add($db, $event); |
|
443 |
|
if ($r !== TRUE) { |
|
444 |
|
$ret .= rg_warning('Cannot add event; try again later.'); |
|
445 |
|
break; |
|
446 |
|
} |
|
447 |
|
rg_event_signal_daemon('', 0); |
|
448 |
|
|
|
449 |
|
$mri['merge_in_progress'] = 1; |
|
450 |
|
$mri['HTML:body'] = rg_template( |
|
451 |
|
'repo/mr/merge_in_progress.html', |
|
452 |
|
$rg, TRUE /*xss*/); |
|
453 |
|
} else { |
|
454 |
|
$mri['HTML:body'] = ''; |
|
455 |
|
|
|
456 |
|
if ($mri['done'] > 10) { // already merged |
|
457 |
|
$mri['merge_in_progress'] = 1; |
|
458 |
|
$mri['already_merged'] = 1; |
|
459 |
|
$mri['done_nice'] = |
|
460 |
|
gmdate('Y-m-d H:i', $mri['done']) . ' UTC'; |
|
461 |
|
$mri['can_merge_without_conflicts'] = 0; |
|
462 |
|
} else { |
|
463 |
|
$r = rg_git_merge_without_conflict($rg['repo_path'], |
|
464 |
|
$against, $mri['new_rev']); |
|
465 |
|
if ($r === FALSE) { |
|
466 |
|
$ret .= rg_warning('Error testing if merge will work' |
|
467 |
|
. ' (' . rg_git_error() . ').'); |
|
468 |
|
break; |
|
469 |
|
} |
|
470 |
|
rg_log('DEBUG: cmwc=' . $r); |
|
471 |
|
$mri['can_merge_without_conflicts'] = $r; |
|
472 |
|
|
|
473 |
|
if ($mri['can_merge_without_conflicts'] == 0) { |
|
474 |
|
$base = rg_git_merge_base($rg['repo_path'], |
|
475 |
|
$against, $mri['new_rev']); |
|
476 |
|
if ($base === FALSE) { |
|
477 |
|
$ret .= rg_warning('Error: finding base: ' |
|
478 |
|
. rg_git_error() . '.'); |
|
479 |
|
break; |
|
480 |
|
} |
|
481 |
|
|
|
482 |
|
$mri['HTML:status'] = rg_git_merge_tree_html( |
|
483 |
|
$rg['repo_path'], $base, $against, |
|
484 |
|
$mri['new_rev']); |
|
485 |
|
rg_log_ml('DEBUG: status: ' . print_r($mri['HTML:status'], TRUE)); |
|
486 |
|
$mri['HTML:body'] .= rg_template( |
|
487 |
|
'repo/mr/conflicts.html', $mri, TRUE /*xss*/); |
|
488 |
|
} |
|
489 |
|
} |
|
490 |
|
|
|
491 |
|
$_log = rg_git_log($rg['repo_path'], 0, $mri['old_rev'], |
|
492 |
|
$mri['new_rev'], TRUE); |
|
493 |
|
if ($_log === FALSE) { |
|
494 |
|
$ret .= rg_warning('Error generating patch.'); |
|
495 |
|
break; |
|
496 |
|
} |
|
497 |
|
|
|
498 |
|
$mri['HTML:body'] .= |
|
499 |
|
rg_git_log2listing($_log, $rg, TRUE); |
|
500 |
|
|
|
501 |
|
if ($mri['can_merge_without_conflicts'] == 1) |
|
502 |
|
$rg['rg_form_token'] = rg_token_get($db, $rg, 'mr_merge'); |
|
503 |
|
} |
|
504 |
|
|
|
505 |
|
//rg_log_ml('DEBUG: mri: ' . print_r($mri, TRUE)); |
|
506 |
|
$rg['mr'] = $mri; |
|
507 |
|
|
|
508 |
|
$hints = array(); |
|
509 |
|
$hints[]['HTML:hint'] = rg_template('hints/repo/merge.html', |
|
510 |
|
$rg, TRUE /*xss*/); |
|
511 |
|
$rg['mr']['HTML:hints'] = rg_template_table('hints/list', |
|
512 |
|
$hints, $rg); |
|
513 |
|
|
|
514 |
|
$ret .= rg_template('repo/mr/page.html', $rg, |
|
515 |
|
TRUE/*xss*/); |
|
516 |
|
break; |
|
517 |
|
} |
|
518 |
|
|
|
519 |
|
rg_log_exit(); |
|
520 |
|
rg_prof_end('mr_high_level'); |
|
521 |
|
return $ret; |
|
522 |
|
} |
|
523 |
|
|
253 |
524 |
?> |
?> |
File inc/user/repo-page.php changed (mode: 100644) (index 6a37182..9e191ae) |
... |
... |
$rg['ssh'] = rg_re_repo_ssh($organization, $user, $repo); |
64 |
64 |
$rg['git'] = rg_re_repo_git($organization, $user, $repo); |
$rg['git'] = rg_re_repo_git($organization, $user, $repo); |
65 |
65 |
$rg['can_admin'] = $can_admin; |
$rg['can_admin'] = $can_admin; |
66 |
66 |
$rg['HTML:hints'] = ''; |
$rg['HTML:hints'] = ''; |
|
67 |
|
$rg['mr'] = array('id' => ''); |
67 |
68 |
|
|
68 |
|
$repo_path = rg_repo_path_by_id($rg['ri']['uid'], $rg['ri']['repo_id']); |
|
69 |
|
rg_log("repo_path=$repo_path"); |
|
70 |
|
putenv("GIT_DIR=$repo_path"); // TODO: this will be removed after all functios will got a path para |
|
|
69 |
|
$rg['repo_path'] = rg_repo_path_by_id($rg['ri']['uid'], $rg['ri']['repo_id']); |
|
70 |
|
rg_log('repo_path=' . $rg['repo_path']); |
|
71 |
|
putenv('GIT_DIR=' . $rg['repo_path']); // TODO: this will be removed after all functios will got a path para |
71 |
72 |
|
|
72 |
73 |
$rg['HTML:menu_repo_level2'] = ''; |
$rg['HTML:menu_repo_level2'] = ''; |
73 |
74 |
$rg['HTML:branches_and_tags'] = ''; |
$rg['HTML:branches_and_tags'] = ''; |
|
... |
... |
if (strcmp($_subop, "history") == 0) { |
141 |
142 |
$ref = $type_ref['ref_path']; |
$ref = $type_ref['ref_path']; |
142 |
143 |
$rg = array_merge($rg, $type_ref); |
$rg = array_merge($rg, $type_ref); |
143 |
144 |
|
|
144 |
|
$bt = rg_git_branches_and_tags($repo_path, $rg['ri']['url_repo'], |
|
|
145 |
|
$bt = rg_git_branches_and_tags($rg['repo_path'], $rg['ri']['url_repo'], |
145 |
146 |
$type_ref['ref_url']); |
$type_ref['ref_url']); |
146 |
147 |
$rg = array_merge($rg, $bt); |
$rg = array_merge($rg, $bt); |
147 |
148 |
|
|
|
... |
... |
if (strcmp($_subop, "history") == 0) { |
159 |
160 |
// find hash of blob |
// find hash of blob |
160 |
161 |
$_path = implode("/", $paras); |
$_path = implode("/", $paras); |
161 |
162 |
$rg['path'] = "/" . $_path; |
$rg['path'] = "/" . $_path; |
162 |
|
$_tree = rg_git_ls_tree($repo_path, $ref, $_path); |
|
|
163 |
|
$_tree = rg_git_ls_tree($rg['repo_path'], $ref, $_path); |
163 |
164 |
if ($_tree === FALSE) { |
if ($_tree === FALSE) { |
164 |
165 |
$_repo_body .= rg_warning('Error: ' . rg_git_error()); |
$_repo_body .= rg_warning('Error: ' . rg_git_error()); |
165 |
166 |
} else { |
} else { |
|
... |
... |
if (strcmp($_subop, "history") == 0) { |
179 |
180 |
// find treeish of dir |
// find treeish of dir |
180 |
181 |
$_path = implode("/", $paras); |
$_path = implode("/", $paras); |
181 |
182 |
$rg['path'] = "/" . $_path; |
$rg['path'] = "/" . $_path; |
182 |
|
$_tree = rg_git_ls_tree($repo_path, $ref, $_path); |
|
|
183 |
|
$_tree = rg_git_ls_tree($rg['repo_path'], $ref, $_path); |
183 |
184 |
if ($_tree === FALSE) { |
if ($_tree === FALSE) { |
184 |
185 |
$_repo_body .= rg_warning('Error: ' . rg_git_error()); |
$_repo_body .= rg_warning('Error: ' . rg_git_error()); |
185 |
186 |
} else { |
} else { |
186 |
187 |
$_hash = $_tree[0]['ref']; |
$_hash = $_tree[0]['ref']; |
187 |
|
$_tree = rg_git_ls_tree($repo_path, $_hash, ""); |
|
|
188 |
|
$_tree = rg_git_ls_tree($rg['repo_path'], |
|
189 |
|
$_hash, ''); |
188 |
190 |
if ($_tree === FALSE) |
if ($_tree === FALSE) |
189 |
191 |
$_repo_body .= rg_warning('Error: ' . rg_git_error()); |
$_repo_body .= rg_warning('Error: ' . rg_git_error()); |
190 |
192 |
else |
else |
|
... |
... |
if (strcmp($_subop, "history") == 0) { |
193 |
195 |
} |
} |
194 |
196 |
} else { // default is to show root tree |
} else { // default is to show root tree |
195 |
197 |
$rg['path'] = ""; |
$rg['path'] = ""; |
196 |
|
$_tree = rg_git_ls_tree($repo_path, $ref, ""); |
|
|
198 |
|
$_tree = rg_git_ls_tree($rg['repo_path'], $ref, ''); |
197 |
199 |
if ($_tree === FALSE) |
if ($_tree === FALSE) |
198 |
200 |
$_repo_body .= rg_warning('Error: ' . rg_git_error()); |
$_repo_body .= rg_warning('Error: ' . rg_git_error()); |
199 |
201 |
else |
else |
|
... |
... |
if (strcmp($_subop, "history") == 0) { |
202 |
204 |
} |
} |
203 |
205 |
} else { // show the log |
} else { // show the log |
204 |
206 |
// TODO: improve the error report (error or empty?) |
// TODO: improve the error report (error or empty?) |
205 |
|
$log = rg_git_log($repo_path, 10, "", $ref, FALSE); |
|
|
207 |
|
$log = rg_git_log($rg['repo_path'], 10, '', $ref, FALSE); |
206 |
208 |
if ($log === FALSE) { |
if ($log === FALSE) { |
207 |
209 |
$_repo_body .= rg_template("repo/not_init.html", $rg, |
$_repo_body .= rg_template("repo/not_init.html", $rg, |
208 |
210 |
TRUE /*xss*/); |
TRUE /*xss*/); |
|
... |
... |
if (strcmp($_subop, "history") == 0) { |
236 |
238 |
$second = $commit; |
$second = $commit; |
237 |
239 |
} |
} |
238 |
240 |
|
|
239 |
|
$log = rg_git_log($repo_path, 1, $first, $second, TRUE); |
|
|
241 |
|
$log = rg_git_log($rg['repo_path'], 1, $first, $second, |
|
242 |
|
TRUE); |
240 |
243 |
$_repo_body .= rg_git_log2listing($log, $rg, FALSE); |
$_repo_body .= rg_git_log2listing($log, $rg, FALSE); |
241 |
244 |
} |
} |
242 |
245 |
} |
} |
|
... |
... |
if (strcmp($_subop, "history") == 0) { |
246 |
249 |
} else if (strcmp($_subop, "stats") == 0) { |
} else if (strcmp($_subop, "stats") == 0) { |
247 |
250 |
$_repo_body .= rg_repo_stats($rg); |
$_repo_body .= rg_repo_stats($rg); |
248 |
251 |
} else if (strcmp($_subop, "mr") == 0) { |
} else if (strcmp($_subop, "mr") == 0) { |
249 |
|
if ($rg['ri']['git_dir_done'] == 0) { |
|
250 |
|
$_repo_body .= rg_template("repo/no_git_dir.html", |
|
251 |
|
$rg, TRUE /*xss*/); |
|
252 |
|
} else { |
|
253 |
|
$_repo_body .= rg_template("repo/mrs.html", $rg, TRUE /*xss*/); |
|
254 |
|
|
|
255 |
|
while (1) { |
|
256 |
|
if (empty($paras)) { |
|
257 |
|
$r = rg_mr_load($db, $rg['ri']['repo_id'], 0 /*no limit*/); |
|
258 |
|
if ($r === FALSE) { |
|
259 |
|
$_repo_body .= "Error getting merge request list (" |
|
260 |
|
. rg_mr_error() . ")."; |
|
261 |
|
} else { |
|
262 |
|
$_repo_body .= rg_template_table("repo/mr/list", |
|
263 |
|
$r, $rg); |
|
264 |
|
} |
|
265 |
|
break; |
|
266 |
|
} |
|
267 |
|
|
|
268 |
|
$mr = sprintf('%u', array_shift($paras)); |
|
269 |
|
$rg['mr'] = $mr; |
|
270 |
|
$mri = rg_mr_load_one($db, $rg['ri']['repo_id'], $mr); |
|
271 |
|
if ($mri === FALSE) { |
|
272 |
|
$_repo_body .= "Error getting merge request" |
|
273 |
|
. " (" . rg_mr_error() . ")."; |
|
274 |
|
break; |
|
275 |
|
} |
|
276 |
|
|
|
277 |
|
$_log = rg_git_log($repo_path, 0, $mri['old_rev'], |
|
278 |
|
$mri['new_rev'], TRUE); |
|
279 |
|
if ($_log === FALSE) { |
|
280 |
|
$_repo_body .= rg_warning("Error generating patch."); |
|
281 |
|
break; |
|
282 |
|
} |
|
283 |
|
|
|
284 |
|
$mri['HTML:diff'] = rg_git_log2listing($_log, $rg, TRUE); |
|
285 |
|
$_repo_body .= rg_template("repo/mr/page.html", $mri, |
|
286 |
|
TRUE /*xss*/); |
|
287 |
|
break; |
|
288 |
|
} |
|
289 |
|
|
|
290 |
|
$hints = array(); |
|
291 |
|
$hints[]['HTML:hint'] = rg_template("hints/repo/merge.html", |
|
292 |
|
$rg, TRUE /*xss*/); |
|
293 |
|
$rg['HTML:hints'] = rg_template_table("hints/list", |
|
294 |
|
$hints, $rg); |
|
295 |
|
} |
|
|
252 |
|
$_repo_body .= rg_mr_high_level($db, $rg, $paras); |
296 |
253 |
} |
} |
297 |
254 |
|
|
298 |
255 |
rg_watch_hl_process($db, $rg, 'repo', $rg['ri']['repo_id'], 0 /*obj_id2*/, |
rg_watch_hl_process($db, $rg, 'repo', $rg['ri']['repo_id'], 0 /*obj_id2*/, |
File tests/pr_anon.php changed (mode: 100644) (index 796444b..9ab4a67) |
... |
... |
$rg_event_socket = "/var/lib/rocketgit/sockets/event.sock"; |
25 |
25 |
|
|
26 |
26 |
|
|
27 |
27 |
rg_log(''); |
rg_log(''); |
28 |
|
rg_log("Creating user..."); |
|
|
28 |
|
rg_log_enter('Creating user...'); |
29 |
29 |
rg_test_create_user($db, $rg_ui); |
rg_test_create_user($db, $rg_ui); |
|
30 |
|
rg_log_exit(); |
30 |
31 |
|
|
31 |
32 |
|
|
32 |
33 |
rg_log(''); |
rg_log(''); |
33 |
|
rg_log('Creating a repo'); |
|
|
34 |
|
rg_log_enter('Login...'); |
|
35 |
|
$r = test_login($test_url, $rg_ui, $good_sid); |
|
36 |
|
if ($r === FALSE) { |
|
37 |
|
rg_log("Cannot login!"); |
|
38 |
|
exit(1); |
|
39 |
|
} |
|
40 |
|
rg_log_exit(); |
|
41 |
|
|
|
42 |
|
|
|
43 |
|
rg_log(''); |
|
44 |
|
rg_log_enter('Creating and upload a ssh key...'); |
|
45 |
|
rg_test_upload_ssh_key($db, $rg_ui, 'pr_anon', $good_sid); |
|
46 |
|
rg_log_exit(); |
|
47 |
|
|
|
48 |
|
|
|
49 |
|
rg_log(''); |
|
50 |
|
rg_log_enter('Creating a repo'); |
34 |
51 |
$repo = array('repo_id' => 0, 'public' => 1); |
$repo = array('repo_id' => 0, 'public' => 1); |
35 |
52 |
rg_test_create_repo($db, $rg_ui, $repo); |
rg_test_create_repo($db, $rg_ui, $repo); |
|
53 |
|
rg_log_exit(); |
|
54 |
|
|
36 |
55 |
|
|
|
56 |
|
$url = '/user/' . $rg_ui['username'] . '/' . $repo['name'] . '/mr/'; |
37 |
57 |
|
|
|
58 |
|
|
|
59 |
|
// TODO: still needed?! Now, we have it by default. |
|
60 |
|
if (0) { |
38 |
61 |
rg_log(''); |
rg_log(''); |
39 |
|
rg_log("Giving anon push rights to any user"); |
|
|
62 |
|
rg_log_enter("Giving anon push rights to any user"); |
40 |
63 |
$x = array(); |
$x = array(); |
41 |
64 |
$x['right_id'] = 0; |
$x['right_id'] = 0; |
42 |
65 |
$x['who'] = $rg_ui['uid']; |
$x['who'] = $rg_ui['uid']; |
|
... |
... |
if ($r !== TRUE) { |
52 |
75 |
rg_log("We cannot give rights to the user"); |
rg_log("We cannot give rights to the user"); |
53 |
76 |
exit(1); |
exit(1); |
54 |
77 |
} |
} |
|
78 |
|
rg_log_exit(); |
|
79 |
|
} |
55 |
80 |
|
|
56 |
81 |
|
|
57 |
82 |
rg_log(''); |
rg_log(''); |
58 |
|
rg_log('Do an anonymous push...'); |
|
59 |
|
system('rm -rf pr_anon.git'); |
|
60 |
|
system('git init pr_anon.git'); |
|
61 |
|
system('cd pr_anon.git; echo "change1" > a'); |
|
62 |
|
system('cd pr_anon.git; git add a; git commit -m "change1 desc"'); |
|
63 |
|
system('cd pr_anon.git; echo "change2" > a; git commit -a -m "change2 desc"'); |
|
64 |
|
//system('cd pr_anon.git; git remote add origin ' |
|
65 |
|
// . ' ssh://rocketgit@' . $rg_ssh_host . ':' . $rg_ssh_port |
|
66 |
|
// . '/user/' . escapeshellarg($rg_ui['username']) . '/' |
|
67 |
|
// . escapeshellarg($repo['name'])); |
|
68 |
|
system('cd pr_anon.git; git remote add origin ' |
|
|
83 |
|
rg_log_enter('Preparing repo...'); |
|
84 |
|
system('rm -rf _pr_anon.git'); |
|
85 |
|
system('git init _pr_anon.git'); |
|
86 |
|
system('cd _pr_anon.git; git remote add origin_ssh ' |
|
87 |
|
. ' ssh://rocketgit@' . $rg_ssh_host . ':' . $rg_ssh_port |
|
88 |
|
. '/user/' . escapeshellarg($rg_ui['username']) . '/' |
|
89 |
|
. escapeshellarg($repo['name'])); |
|
90 |
|
system('cd _pr_anon.git; git remote add origin_git ' |
69 |
91 |
. ' git://' . $rg_git_host . ':' . $rg_git_port |
. ' git://' . $rg_git_host . ':' . $rg_git_port |
70 |
92 |
. '/user/' . escapeshellarg($rg_ui['username']) . '/' |
. '/user/' . escapeshellarg($rg_ui['username']) . '/' |
71 |
93 |
. escapeshellarg($repo['name'])); |
. escapeshellarg($repo['name'])); |
72 |
|
system('cd pr_anon.git; git push origin master'); |
|
|
94 |
|
rg_log_exit(); |
73 |
95 |
|
|
74 |
96 |
|
|
75 |
97 |
rg_log(''); |
rg_log(''); |
76 |
|
rg_log('Check if the pull request has been done...'); |
|
77 |
|
$tries = 10; |
|
78 |
|
while ($tries > 0) { |
|
79 |
|
$sql = 'SELECT * FROM merge_requests WHERE repo_id = ' . $repo['repo_id']; |
|
80 |
|
$res = rg_sql_query($db, $sql); |
|
81 |
|
$rows = rg_sql_num_rows($res); |
|
82 |
|
if ($rows > 0) |
|
83 |
|
$row = rg_sql_fetch_array($res); |
|
84 |
|
rg_sql_free_result($res); |
|
85 |
|
if ($rows > 0) |
|
86 |
|
break; |
|
|
98 |
|
rg_log_enter('Do an non-anonymous push...'); |
|
99 |
|
system('export GIT_SSH_COMMAND="ssh -o IdentityFile=../keys/pr_anon";' |
|
100 |
|
. 'cd _pr_anon.git; echo "change1" > a;' |
|
101 |
|
. 'git add a; git commit -m "change1 desc";' |
|
102 |
|
. 'echo "change2" > a; git commit -a -m "change2 desc";' |
|
103 |
|
. 'git push origin_ssh master'); |
|
104 |
|
rg_log_exit(); |
87 |
105 |
|
|
88 |
|
sleep(1); |
|
89 |
|
$tries--; |
|
|
106 |
|
|
|
107 |
|
rg_log(''); |
|
108 |
|
rg_log_enter('Do an anonymous push...'); |
|
109 |
|
system('cd _pr_anon.git; echo "change3" >> a;' |
|
110 |
|
. 'git add a; git commit -m "anon change1 desc";' |
|
111 |
|
. 'echo "change4" >> a; git commit -a -m "anon change2 desc";' |
|
112 |
|
. 'git push origin_git master'); |
|
113 |
|
rg_log_exit(); |
|
114 |
|
|
|
115 |
|
|
|
116 |
|
rg_log(''); |
|
117 |
|
rg_log_enter('Check if merge is in db and is agains correct branch...'); |
|
118 |
|
$mri = rg_test_mr_in_db($db, $repo['repo_id']); |
|
119 |
|
if (strcmp($mri['refname'], 'refs/heads/master') != 0) { |
|
120 |
|
rg_log_ml('mri: ' . print_r($mri, TRUE)); |
|
121 |
|
rg_log('Seems the ref is not master: ' . $mri['refname'] . '!'); |
|
122 |
|
exit(1); |
90 |
123 |
} |
} |
91 |
|
if ($rows == 0) { |
|
92 |
|
rg_log('Seems the pull request did not hit the database!'); |
|
|
124 |
|
rg_log_exit(); |
|
125 |
|
|
|
126 |
|
|
|
127 |
|
rg_log(''); |
|
128 |
|
rg_log_enter('Loading the merge requests page - just to see it appears there'); |
|
129 |
|
$data = array(); |
|
130 |
|
$headers = array("Cookie: sid=" . $good_sid); |
|
131 |
|
$r = do_req($test_url . '/user/' . $rg_ui['username'] |
|
132 |
|
. '/' . $repo['name'] . '/mr?t=pr_anon', $data, $headers); |
|
133 |
|
if (!strstr($r['body'], '>' . $mri['id'] . '<')) { |
|
134 |
|
rg_log_ml('r: ' . print_r($r, TRUE)); |
|
135 |
|
rg_log('id link not found!'); |
93 |
136 |
exit(1); |
exit(1); |
94 |
137 |
} |
} |
95 |
|
$ns = $row['namespace']; |
|
96 |
|
$ref = $row['refname']; |
|
97 |
|
if (strcmp($ref, 'refs/heads/master') != 0) { |
|
98 |
|
rg_log('Seems the ref is not master: ' . $ref . '!'); |
|
|
138 |
|
rg_log_exit(); |
|
139 |
|
|
|
140 |
|
|
|
141 |
|
rg_log(''); |
|
142 |
|
rg_log_enter('Loading the merge request specific page'); |
|
143 |
|
$data = array(); |
|
144 |
|
$headers = array("Cookie: sid=" . $good_sid); |
|
145 |
|
$r = do_req($test_url . $url . $mri['id'] . '?t=pr_anon', $data, $headers); |
|
146 |
|
if (!strstr($r['body'], 'This pull request can be merged without conflicts')) { |
|
147 |
|
rg_log_ml('r: ' . print_r($r, TRUE)); |
|
148 |
|
rg_log('Pull request does not appear as mergeable'); |
99 |
149 |
exit(1); |
exit(1); |
100 |
150 |
} |
} |
|
151 |
|
rg_log_exit(); |
101 |
152 |
|
|
102 |
153 |
|
|
103 |
154 |
rg_log(''); |
rg_log(''); |
104 |
|
rg_log('Login, so we can load the merge request...'); |
|
105 |
|
$r = test_login($test_url, $rg_ui, $good_sid); |
|
|
155 |
|
rg_log_enter('Merging pull request...'); |
|
156 |
|
$data = array('token' => $r['tokens']['mr_merge'], |
|
157 |
|
'merge_ff' => 0, 'merge_msg' => 'This is the merge message <xss>'); |
|
158 |
|
$r = do_req($test_url . $url . $mri['id'] . '/merge', $data, $headers); |
106 |
159 |
if ($r === FALSE) { |
if ($r === FALSE) { |
107 |
|
rg_log("Cannot login!"); |
|
|
160 |
|
rg_log('Cannot post merge form'); |
108 |
161 |
exit(1); |
exit(1); |
109 |
162 |
} |
} |
|
163 |
|
$tries = 0; |
|
164 |
|
while (1) { |
|
165 |
|
$sql = 'SELECT * FROM merge_requests' |
|
166 |
|
. ' WHERE repo_id = ' . $repo['repo_id'] |
|
167 |
|
. ' AND done > 0 AND id = ' . $mri['id']; |
|
168 |
|
$res = rg_sql_query($db, $sql); |
|
169 |
|
$rows = rg_sql_num_rows($res); |
|
170 |
|
rg_sql_free_result($res); |
|
171 |
|
if ($rows == 1) |
|
172 |
|
break; |
|
173 |
|
|
|
174 |
|
if ($tries == 10) { |
|
175 |
|
rg_log('merge_request was not marked as done!'); |
|
176 |
|
exit(1); |
|
177 |
|
} |
|
178 |
|
$tries++; |
|
179 |
|
sleep(1); |
|
180 |
|
} |
|
181 |
|
rg_log_exit(); |
110 |
182 |
|
|
111 |
183 |
|
|
112 |
184 |
rg_log(''); |
rg_log(''); |
113 |
|
rg_log('Loading the merge requests page - just to see it appears there'); |
|
|
185 |
|
rg_log_enter('Now, try to see what happens when a merge is with conflicts...'); |
|
186 |
|
system('cd _pr_anon.git;' |
|
187 |
|
. 'git pull origin_git master;' |
|
188 |
|
. 'echo "change2" > a;' |
|
189 |
|
. 'git commit -a -m "conflict1b";' |
|
190 |
|
. 'git push origin_git master'); |
|
191 |
|
system('export GIT_SSH_COMMAND="ssh -o IdentityFile=../keys/pr_anon";' |
|
192 |
|
. 'cd _pr_anon.git;' |
|
193 |
|
. 'git reset --hard HEAD^1;' |
|
194 |
|
. ' echo "change1" > a;' |
|
195 |
|
. 'git commit -a -m "conflict1a";' |
|
196 |
|
. 'git push origin_ssh master'); |
|
197 |
|
$mri = rg_test_mr_in_db($db, $repo['repo_id']); |
114 |
198 |
$data = array(); |
$data = array(); |
115 |
199 |
$headers = array("Cookie: sid=" . $good_sid); |
$headers = array("Cookie: sid=" . $good_sid); |
116 |
|
$r = do_req($test_url . '/user/' . $rg_ui['username'] |
|
117 |
|
. '/' . $repo['name'] . '/mr?t=pr_anon', $data, $headers); |
|
118 |
|
if (!strstr($r['body'], '>' . $ns . '<')) { |
|
|
200 |
|
$r = do_req($test_url . $url . $mri['id'] . '?t=pr_anon', $data, $headers); |
|
201 |
|
if (!strstr($r['body'], 'This pull request cannot be merged without conflicts')) { |
119 |
202 |
rg_log_ml('r: ' . print_r($r, TRUE)); |
rg_log_ml('r: ' . print_r($r, TRUE)); |
120 |
|
rg_log('namespace link not found!'); |
|
|
203 |
|
rg_log('Pull request does not appear as non-mergeable'); |
121 |
204 |
exit(1); |
exit(1); |
122 |
205 |
} |
} |
|
206 |
|
rg_log_exit(); |
123 |
207 |
|
|
124 |
208 |
|
|
125 |
209 |
rg_log(''); |
rg_log(''); |
126 |
|
rg_log('Loading the merge request specific page'); |
|
|
210 |
|
rg_log_enter('Loading conflicts page...'); |
127 |
211 |
$data = array(); |
$data = array(); |
128 |
212 |
$headers = array("Cookie: sid=" . $good_sid); |
$headers = array("Cookie: sid=" . $good_sid); |
129 |
|
$r = do_req($test_url . '/user/' . $rg_ui['username'] |
|
130 |
|
. '/' . $repo['name'] . '/mr/' . $ns . '?t=pr_anon', $data, $headers); |
|
131 |
|
rg_log_ml('r: ' . print_r($r, TRUE)); |
|
132 |
|
|
|
|
213 |
|
$r = do_req($test_url . $url . $mri['id'] . '?t=pr_anon', $data, $headers); |
|
214 |
|
if (!strstr($r['body'], 'Conflicts:')) { |
|
215 |
|
rg_log_ml('r: ' . print_r($r, TRUE)); |
|
216 |
|
rg_log('Errors in conflicts page!'); |
|
217 |
|
exit(1); |
|
218 |
|
} |
|
219 |
|
rg_log_exit(); |
133 |
220 |
|
|
134 |
221 |
rg_log("OK!"); |
rg_log("OK!"); |
135 |
222 |
?> |
?> |