xaizek / rocketgit (License: AGPLv3+) (since 2018-12-09)
Light and fast Git hosting solution suitable to serve both as a hub or as a personal code storage with its tickets, pull requests, API and much more.
Commit e51ecf91f18a7533a009530075bb0710e4caae63

Cache improvements (no wait when no needed) and layout changes.
Author: Catalin(ux) M. BOIE
Author date (UTC): 2015-07-02 19:39
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2015-07-02 19:39
Parent(s): 3aaa0b5b7cc18277a8ca4b404c40b0eb15383681
Signing key:
Tree: 7acdfd22ff0dd7ece400a61ae0ee053870d3fdae
File Lines added Lines deleted
TODO 8 6
duilder.conf 1 1
inc/bug.inc.php 1 1
inc/cache.inc.php 18 5
inc/repo.inc.php 1 1
inc/token.inc.php 1 1
inc/user.inc.php 12 31
inc/user/repo-page.php 6 4
rocketgit.spec.in 1 1
root/index.php 1 1
root/themes/default/index.html 2 1
root/themes/default/mail/user/welcome.body.txt 3 3
root/themes/default/main.css 2 0
root/themes/default/main.html 6 4
scripts/cache.php 6 2
File TODO changed (mode: 100644) (index c713968..f4cc376)
1 1 == Where I stopped last time == == Where I stopped last time ==
2 [ ] admin_delete_rights::delete, was not protected against csrf/ua!
3 Other places? Use a unit test for this stuff?
4 [ ] Seems I do not insert a history item on repo creation!
5 [ ] Bugs caching page is not working anymore (after NO_WAIT changes)
6 Seems I regenerate the CSRF tokens!
7 [ ] tests are failing!
8 2 [ ] [ ]
9 3
4
10 5 == CSRF logic == == CSRF logic ==
11 6 - Generate a token for a specific form (call rg_token_get with an $op) - Generate a token for a specific form (call rg_token_get with an $op)
12 7 Why I do not use a key per user not a master key?! Maybe because I have Why I do not use a key per user not a master key?! Maybe because I have
 
... ... to store it in db. Why not? Because of caching of the pages...
21 16
22 17
23 18 == BEFORE NEXT RELEASE == == BEFORE NEXT RELEASE ==
19 [ ] Prefetch of varibles from cache
20 Take care of non-existing vars in cache.
21 First candidate: first_install.
22 [ ] Seems I do not insert a history item on repo creation!
23 [ ] admin_delete_rights::delete, was not protected against csrf/ua!
24 Other places? Use a unit test for this stuff?
25 [ ] When building VM, automatically add a snapshot, so user can go back.
24 26 [ ] Some rg_cache_unset may trigger an error. Case by case we have to [ ] Some rg_cache_unset may trigger an error. Case by case we have to
25 27 analyze the impact. We may want to give an error to the user. analyze the impact. We may want to give an error to the user.
26 28 I am thinking at tokens. Maybe we do ot want to mark it as used in I am thinking at tokens. Maybe we do ot want to mark it as used in
File duilder.conf changed (mode: 100644) (index 8d2fdc2..3d10ee8)
1 1 PRJ="rocketgit" PRJ="rocketgit"
2 VER="0.35"
2 VER="0.36"
3 3 REV="1" REV="1"
4 4 EXCLUDE=".exclude" EXCLUDE=".exclude"
5 5 EXPORT_PATH="/data/www/umbrella/kernel/us/rocketgit" EXPORT_PATH="/data/www/umbrella/kernel/us/rocketgit"
File inc/bug.inc.php changed (mode: 100644) (index 8273d34..3eca52d)
... ... function rg_bug_delete_undelete($db, $who, $repo_id, $bug_id, $op)
593 593 $new['deleted_who'] = $who; $new['deleted_who'] = $who;
594 594 rg_bug_cosmetic($db, $new); rg_bug_cosmetic($db, $new);
595 595 $key = $repo_id . "::bugs::" . $bug_id; $key = $repo_id . "::bugs::" . $bug_id;
596 rg_cache_merge($key, $new);
596 rg_cache_merge($key, $new, RG_SOCKET_NO_WAIT);
597 597
598 598 $ret = TRUE; $ret = TRUE;
599 599 break; break;
File inc/cache.inc.php changed (mode: 100644) (index 2fece33..5702ab5)
... ... function rg_cache_core_merge($ns_var, $list)
82 82 $t = explode("::", $ns_var); $t = explode("::", $ns_var);
83 83 foreach ($t as $token) { foreach ($t as $token) {
84 84 if (!isset($tree[$token])) if (!isset($tree[$token]))
85 $tree[$token] = array();
85 return FALSE;
86 86
87 87 $tree = &$tree[$token]; $tree = &$tree[$token];
88 88 } }
89 89
90 90 foreach ($list as $k => $v) foreach ($list as $k => $v)
91 91 $tree[$k] = $v; $tree[$k] = $v;
92
93 return TRUE;
92 94 } }
93 95
94 96 /* /*
 
... ... function rg_cache_unset($ns_var, $flags)
498 500 /* /*
499 501 * Merge some k=v pairs into an existing cache * Merge some k=v pairs into an existing cache
500 502 */ */
501 function rg_cache_merge($ns_var, $list)
503 function rg_cache_merge($ns_var, $list, $flags)
502 504 { {
503 505 global $rg_cache_socket; global $rg_cache_socket;
504 506 global $rg_cache_timeout; global $rg_cache_timeout;
 
... ... function rg_cache_merge($ns_var, $list)
507 509
508 510 rg_prof_start("cache_merge"); rg_prof_start("cache_merge");
509 511 if ($rg_cache_debug) if ($rg_cache_debug)
510 rg_log_ml_enter("cache_merge: $ns_var = " . print_r($list, TRUE));
512 rg_log_ml_enter("cache_merge: flags=$flags"
513 . " $ns_var = " . print_r($list, TRUE));
511 514
512 515 $ret = FALSE; $ret = FALSE;
513 516 while (1) { while (1) {
 
... ... function rg_cache_merge($ns_var, $list)
516 519 if ($rg_cache_enable === FALSE) if ($rg_cache_enable === FALSE)
517 520 break; break;
518 521
519 $c = rg_socket($rg_cache_socket, "MERGE F= " . $ns_var . "="
520 . rg_cache_prepare($list) . "\n", $rg_cache_timeout, 1, 0);
522 $f = '';
523 if ($flags & RG_SOCKET_NO_WAIT)
524 $f .= 'W';
525
526 $c = rg_socket($rg_cache_socket, "MERGE F=$f " . $ns_var . "="
527 . rg_cache_prepare($list) . "\n", $rg_cache_timeout,
528 1, $flags);
521 529 if ($c === FALSE) if ($c === FALSE)
522 530 break; break;
523 531
532 if ($flags & RG_SOCKET_NO_WAIT) {
533 $ret = TRUE;
534 break;
535 }
536
524 537 if (strncmp($c, "OK", 2) != 0) if (strncmp($c, "OK", 2) != 0)
525 538 break; break;
526 539
File inc/repo.inc.php changed (mode: 100644) (index a13e3cb..d59afe3)
... ... function rg_repo_git_done($db, $repo_id)
1205 1205 $params = array("repo_id" => $repo_id); $params = array("repo_id" => $repo_id);
1206 1206
1207 1207 rg_cache_merge('repo_by_id::' . $repo_id, rg_cache_merge('repo_by_id::' . $repo_id,
1208 array('git_dir_done' => 1));
1208 array('git_dir_done' => 1), RG_SOCKET_NO_WAIT);
1209 1209
1210 1210 $sql = "UPDATE repos SET git_dir_done = 1" $sql = "UPDATE repos SET git_dir_done = 1"
1211 1211 . " WHERE repo_id = @@repo_id@@"; . " WHERE repo_id = @@repo_id@@";
File inc/token.inc.php changed (mode: 100644) (index f7e5774..be41c1f)
... ... function rg_token_valid($db, $rg, $tag, $double_allowed)
214 214 function rg_token_get($db, $rg, $tag) function rg_token_get($db, $rg, $tag)
215 215 { {
216 216 rg_log_enter('token_get: sid=' . $rg['sid'] . ' tag=' . $tag rg_log_enter('token_get: sid=' . $rg['sid'] . ' tag=' . $tag
217 . 'ua=' . $rg['ua']);
217 . ' ua=' . $rg['ua']);
218 218
219 219 $ret = FALSE; $ret = FALSE;
220 220 while (1) { while (1) {
File inc/user.inc.php changed (mode: 100644) (index 921d99d..351bbf7)
... ... function rg_user_edit($db, $d)
442 442 } }
443 443 } }
444 444
445 $now = time();
445 $d['itime'] = time();
446 446 $d['salt'] = rg_id(40); $d['salt'] = rg_id(40);
447 447 $d['pass_crypted'] = rg_user_pass($d['salt'], $d['pass']); $d['pass_crypted'] = rg_user_pass($d['salt'], $d['pass']);
448 448
449 $params = array("username" => $d['username'],
450 "realname" => $d['realname'],
451 "salt" => $d['salt'],
452 "pass_crypted" => $d['pass_crypted'],
453 "email" => $d['email'],
454 "now" => $now,
455 "is_admin" => $d['is_admin'],
456 "rights" => $d['rights'],
457 "session_time" => $d['session_time'],
458 "confirmed" => $confirmed,
459 "confirm_token" => $d['confirm_token'],
460 "plan_id" => $d['plan_id'],
461 "uid" => $d['uid']);
462
463 449 if ($d['uid'] == 0) { // add if ($d['uid'] == 0) { // add
464 450 if (rg_user_pass_ok($d['pass']) !== TRUE) if (rg_user_pass_ok($d['pass']) !== TRUE)
465 451 break; break;
 
... ... function rg_user_edit($db, $d)
469 455 . ", is_admin, rights, session_time" . ", is_admin, rights, session_time"
470 456 . ", confirmed, confirm_token, plan_id)" . ", confirmed, confirm_token, plan_id)"
471 457 . " VALUES (@@username@@, @@realname@@, @@salt@@" . " VALUES (@@username@@, @@realname@@, @@salt@@"
472 . ", @@pass_crypted@@, @@email@@, @@now@@"
458 . ", @@pass_crypted@@, @@email@@, @@itime@@"
473 459 . ", @@is_admin@@, @@rights@@, @@session_time@@" . ", @@is_admin@@, @@rights@@, @@session_time@@"
474 460 . ", @@confirmed@@, @@confirm_token@@, @@plan_id@@)" . ", @@confirmed@@, @@confirm_token@@, @@plan_id@@)"
475 461 . " RETURNING uid"; . " RETURNING uid";
476 462 } else { // edit } else { // edit
477 463 $salt_pass_add = ""; $salt_pass_add = "";
478 464 if (!empty($d['pass'])) { if (!empty($d['pass'])) {
479 $params['pass_crtypted'] = $d['pass_crypted'];
480 $params['salt'] = $d['salt'];
481 465 $salt_pass_add = ", pass = @@pass_crypted@@" $salt_pass_add = ", pass = @@pass_crypted@@"
482 466 . ", salt = @@salt@@"; . ", salt = @@salt@@";
483 467 } }
 
... ... function rg_user_edit($db, $d)
495 479 . " RETURNING uid"; . " RETURNING uid";
496 480 } }
497 481
498 $res = rg_sql_query_params($db, $sql, $params);
482 $res = rg_sql_query_params($db, $sql, $d);
499 483 if ($res === FALSE) { if ($res === FALSE) {
500 484 rg_user_set_error("cannot insert/update user (" . rg_sql_error() . ")"); rg_user_set_error("cannot insert/update user (" . rg_sql_error() . ")");
501 485 break; break;
 
... ... function rg_user_edit($db, $d)
503 487 $row = rg_sql_fetch_array($res); $row = rg_sql_fetch_array($res);
504 488 rg_sql_free_result($res); rg_sql_free_result($res);
505 489
506 // invalidate cache (because we may not have the password)
507 // TODO: but, we can do a merge!
508 if ($d['uid'] > 0)
509 rg_cache_unset('user::' . $d['uid'], RG_SOCKET_NO_WAIT);
510
511 490 if ($d['uid'] == 0) { // add if ($d['uid'] == 0) { // add
491 rg_cache_set('user::' . $d['uid'], $d, RG_SOCKET_NO_WAIT);
492
512 493 $event = array('category' => 2000, 'prio' => 50, $event = array('category' => 2000, 'prio' => 50,
513 494 'ui' => array( 'ui' => array(
514 495 'uid' => $row['uid'], 'uid' => $row['uid'],
 
... ... function rg_user_edit($db, $d)
525 506 break; break;
526 507 } }
527 508 rg_event_signal_daemon("", 0); rg_event_signal_daemon("", 0);
509 } else { // edit
510 rg_cache_merge('user::' . $d['uid'], $d, RG_SOCKET_NO_WAIT);
528 511 } }
529 512
530 513 // TODO: should we cache here the user_by_uid and user_by_name // TODO: should we cache here the user_by_uid and user_by_name
 
... ... function rg_user_set_last_seen($db, $uid)
691 674 } }
692 675 rg_sql_free_result($res); rg_sql_free_result($res);
693 676
694 rg_cache_merge("user::" . $uid, $params);
677 rg_cache_merge("user::" . $uid, $params, RG_SOCKET_NO_WAIT);
695 678
696 679 $ret = TRUE; $ret = TRUE;
697 680 break; break;
 
... ... function rg_user_set_pass($db, $uid, $pass)
1281 1264 } }
1282 1265 rg_sql_free_result($res); rg_sql_free_result($res);
1283 1266
1284 // Because we may not have info about the user in cache,
1285 // we cannot do a merge.
1286 rg_cache_unset('user::' . $uid, RG_SOCKET_NO_WAIT);
1267 rg_cache_merge('user::' . $uid, $params, RG_SOCKET_NO_WAIT);
1287 1268
1288 1269 $ret = TRUE; $ret = TRUE;
1289 1270 break; break;
 
... ... function rg_user_confirm($db, $token)
1330 1311 $uid = $row['uid']; $uid = $row['uid'];
1331 1312
1332 1313 // "< 2" because we mark with "1" if "no need to confirm" // "< 2" because we mark with "1" if "no need to confirm"
1333 $params = array("now" => $now, "uid" => $uid);
1334 $sql = "UPDATE users SET confirmed = @@now@@"
1314 $params = array("confirmed" => $now, "uid" => $uid);
1315 $sql = "UPDATE users SET confirmed = @@confirmed@@"
1335 1316 . " WHERE uid = @@uid@@" . " WHERE uid = @@uid@@"
1336 1317 . " AND confirmed < 2"; . " AND confirmed < 2";
1337 1318 $res = rg_sql_query_params($db, $sql, $params); $res = rg_sql_query_params($db, $sql, $params);
 
... ... function rg_user_confirm($db, $token)
1341 1322 } }
1342 1323 rg_sql_free_result($res); rg_sql_free_result($res);
1343 1324
1344 rg_cache_unset('user::' . $uid, RG_SOCKET_NO_WAIT);
1325 rg_cache_merge('user::' . $uid, $params, RG_SOCKET_NO_WAIT);
1345 1326
1346 1327 $ret = $uid; $ret = $uid;
1347 1328 break; break;
File inc/user/repo-page.php changed (mode: 100644) (index 90ae5c1..1382e1c)
... ... if (strcmp($_subop, "history") == 0) {
177 177 // find treeish of dir // find treeish of dir
178 178 $_path = implode("/", $paras); $_path = implode("/", $paras);
179 179 $rg['path'] = "/" . $_path; $rg['path'] = "/" . $_path;
180 $_tree = rg_git_ls_tree($ref, $_path);
180 $_tree = rg_git_ls_tree($repo_path, $ref, $_path);
181 181 if ($_tree === FALSE) { if ($_tree === FALSE) {
182 182 $_repo_body .= "Invalid path!"; $_repo_body .= "Invalid path!";
183 183 } else { } else {
184 184 $_hash = $_tree[0]['ref']; $_hash = $_tree[0]['ref'];
185 $_tree = rg_git_ls_tree($_hash, "");
185 $_tree = rg_git_ls_tree($repo_path, $_hash, "");
186 186 $_repo_body .= rg_template_table("repo/tree", $_repo_body .= rg_template_table("repo/tree",
187 187 $_tree, $rg); $_tree, $rg);
188 188 } }
189 189 } else { // default is to show root tree } else { // default is to show root tree
190 190 $rg['path'] = ""; $rg['path'] = "";
191 $_tree = rg_git_ls_tree($ref, "");
191 $_tree = rg_git_ls_tree($repo_path, $ref, "");
192 192 $_repo_body .= rg_template_table("repo/tree", $_tree, $_repo_body .= rg_template_table("repo/tree", $_tree,
193 193 $rg); $rg);
194 194 } }
195 195 } else { // show the log } else { // show the log
196 // TODO: improve the error report (error or empty?)
196 197 $log = rg_git_log($repo_path, 10, "", $ref, FALSE); $log = rg_git_log($repo_path, 10, "", $ref, FALSE);
197 198 if ($log === FALSE) { if ($log === FALSE) {
198 $_repo_body .= rg_template("repo/not_init.html", $rg, TRUE /* xss */);
199 $_repo_body .= rg_template("repo/not_init.html", $rg,
200 TRUE /*xss*/);
199 201 } else { } else {
200 202 //rg_log_ml("DEBUG: log: " . print_r($log, TRUE)); //rg_log_ml("DEBUG: log: " . print_r($log, TRUE));
201 203 $_repo_body .= rg_git_log_template($log, "repo/log", $rg); $_repo_body .= rg_git_log_template($log, "repo/log", $rg);
File rocketgit.spec.in changed (mode: 100644) (index b8d149b..a7798b3)
... ... URL: http://kernel.embedromix.ro/us/
14 14 BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
15 15 BuildArch: noarch BuildArch: noarch
16 16 Requires: httpd, php, php-cli, php-pgsql, php-mbstring, xinetd Requires: httpd, php, php-cli, php-pgsql, php-mbstring, xinetd
17 Requires: git, postgresql-server
17 Requires: git, cronie
18 18 Requires: util-linux Requires: util-linux
19 19 # SELinux stuff # SELinux stuff
20 20 # https://fedoraproject.org/wiki/SELinux_Policy_Modules_Packaging_Draft?rd=PackagingDrafts/SELinux/PolicyModules # https://fedoraproject.org/wiki/SELinux_Policy_Modules_Packaging_Draft?rd=PackagingDrafts/SELinux/PolicyModules
File root/index.php changed (mode: 100644) (index 778dd1c..37971f5)
... ... $rg['first_install_text'] = "?";
136 136 $r = rg_state_get($db, "first_install"); $r = rg_state_get($db, "first_install");
137 137 if ($r === FALSE) { if ($r === FALSE) {
138 138 // Probably we cannot connect to database/cache // Probably we cannot connect to database/cache
139 $body .= rg_template('admin/db_error.html', TRUE /* xss */);
139 $body .= rg_template('admin/db_error.html', TRUE /*xss*/);
140 140 } else if ($r === '') { } else if ($r === '') {
141 141 $body .= rg_init($db, $rg); $body .= rg_init($db, $rg);
142 142 } else { } else {
File root/themes/default/index.html changed (mode: 100644) (index 14f850c..aa697c3)
47 47
48 48 <div id="footer"> <div id="footer">
49 49 <div id="footer_logo"> <div id="footer_logo">
50 <img src="@@IMG:logo/rg6.png@@" alt="RocketGit logo" /><br />
50 <img src="@@IMG:logo/rg6.png@@" alt="RocketGit logo" />
51 <br />
51 52 <div class="logo"> <div class="logo">
52 53 <a href="/">RocketGit</a> <a href="/">RocketGit</a>
53 54 <br /> <br />
File root/themes/default/mail/user/welcome.body.txt changed (mode: 100644) (index 782e34f..ab1074d)
... ... Hello!
2 2
3 3 Welcome to RocketGit! Welcome to RocketGit!
4 4
5 We will gladly host your projects.
5 We are happy to host your projects.
6 6 Enjoy your stay! Enjoy your stay!
7 7 @@if(@@rg_account_email_confirm@@ == 1){{ @@if(@@rg_account_email_confirm@@ == 1){{
8 8 You must confirm your e-mail address before you can use your account, You must confirm your e-mail address before you can use your account,
9 by clicking on the link below:
9 by clicking the link below:
10 10 }}{{ }}{{
11 You may want to confirm your e-mail address by clicking on the link below:
11 You may want to confirm your e-mail address by clicking the link below:
12 12 }} }}
13 13 @@url@@/op/confirm/@@ui::confirm_token@@ @@url@@/op/confirm/@@ui::confirm_token@@
14 14
File root/themes/default/main.css changed (mode: 100644) (index 4e88821..f84b638)
... ... form input[type="submit"] {
204 204 #footer_logo { #footer_logo {
205 205 padding: 10px 0; padding: 10px 0;
206 206 float: left; float: left;
207 text-align: center;
207 208 } }
208 209 #footer_logo img { margin-left: auto; margin-right: auto; display: block; } #footer_logo img { margin-left: auto; margin-right: auto; display: block; }
209 210 #footer_info { #footer_info {
 
... ... form input[type="submit"] {
505 506 color: red; color: red;
506 507 font-size: 14pt; font-size: 14pt;
507 508 font-weight: bold; font-weight: bold;
509 padding-bottom: 9px;
508 510 } }
File root/themes/default/main.html changed (mode: 100644) (index 1b9b125..86fd6b8)
2 2
3 3 <div class="island_row"> <div class="island_row">
4 4 <div class="island_cell"> <div class="island_cell">
5 <div class="island">
5 <div class="island" style="background-color: #aaa; color: #fff">
6 6 <div class="island_title">Welcome to RocketGit!</div> <div class="island_title">Welcome to RocketGit!</div>
7 FLOS (free, libre and open-source) software for managing Git projects,
8 both public and private.
9 <font color="red">Beta.</font>
7 <span style="font-weight: bold">
8 FLOS (free, libre and open-source) software for managing Git
9 projects, both public and private.
10 <span style="color: red">Beta</span>
11 </span>
10 12 </div> </div>
11 13 </div> </div>
12 14 </div> </div>
File scripts/cache.php changed (mode: 100644) (index c3f4837..66b6865)
... ... function rg_handle_command($k, &$conn_table, $cmd)
96 96 $value = trim($ns_var_value[1]); $value = trim($ns_var_value[1]);
97 97 $value = unserialize(stripcslashes($value)); $value = unserialize(stripcslashes($value));
98 98 if ($value !== FALSE) { if ($value !== FALSE) {
99 rg_cache_core_merge("normal::" . $ns_var, $value);
100 $buf = "OK\n";
99 $ret = rg_cache_core_merge("normal::" . $ns_var,
100 $value);
101 if ($ret === FALSE)
102 $buf = "NOT_FOUND\n";
103 else
104 $buf = "OK\n";
101 105 } else { } else {
102 106 $buf = "ER cannot unserialize data\n"; $buf = "ER cannot unserialize data\n";
103 107 } }
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://code.reversed.top/user/xaizek/rocketgit

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/rocketgit

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