/** * This is a helper function that just contains a block of code that needs to be * executed from two different places in this script. Consider it more as C macro * than a real function. */ function amos_parse_core_commit() { global $DB; global $stage, $realmodified, $timemodified, $commitmsg, $committer, $committeremail, $commithash, $version, $fullcommitmsg, $startatlock, $affected; // if there is nothing to do, just store the last hash processed and return // this is typical for git commits that do not touch any lang file if (!$stage->has_component()) { file_put_contents($startatlock, $commithash); return; } if (empty($commithash)) { throw new coding_exception('When storing strings from a git commit, the hash must be provided'); } // this is a hacky check to make sure that the git commit has not been processed already // this helps to prevent situations when a commit is reverted and AMOS is adding // and removing strings in sort of loop if ($DB->record_exists('amos_commits', array('source' => 'git', 'commithash' => $commithash))) { $stage->clear(); fputs(STDOUT, "SKIP {$commithash} has already been processed before\n"); file_put_contents($startatlock, $commithash); return; } // rebase the stage so that it contains just real modifications of strings $stage->rebase($timemodified, true, $timemodified); // make sure that the strings to be removed are really affected by the commit foreach ($stage->get_iterator() as $component) { foreach ($component->get_iterator() as $string) { if (!isset($affected[$component->name][$string->id])) { $component->unlink_string($string->id); } } } // rebase again to get rid of eventually empty components that were // left after removing unaffected strings $stage->rebase($timemodified, false); // if there is nothing to do now, just store the last has processed and return. // this is typical for git commits that touch some lang file but they do not actually // modify any string. Note that we do not execute AMOScript in this situation. if (!$stage->has_component()) { fputs(STDOUT, "NOOP {$commithash} does not introduce any string change\n"); file_put_contents($startatlock, $commithash); return; } // ok so it seems we finally have something to do here! let's spam the world first amos_core_commit_notify($stage, $commitmsg, $committer, $committeremail, $commithash, $fullcommitmsg); // actually commit the changes $stage->commit($commitmsg, array('source' => 'git', 'userinfo' => $committer . ' <' . $committeremail . '>', 'commithash' => $commithash), true, $timemodified); // execute AMOS script if the commit message contains some if ($version->code >= mlang_version::MOODLE_20) { $instructions = mlang_tools::extract_script_from_text($fullcommitmsg); if (!empty($instructions)) { foreach ($instructions as $instruction) { fputs(STDOUT, "EXEC {$instruction}\n"); $changes = mlang_tools::execute($instruction, $version, $timemodified); if ($changes instanceof mlang_stage) { $changes->rebase($timemodified); $changes->commit($commitmsg, array('source' => 'commitscript', 'userinfo' => $committer . ' <' . $committeremail . '>', 'commithash' => $commithash), true, $timemodified); } elseif ($changes < 0) { fputs(STDERR, "EXEC STATUS {$changes}\n"); } unset($changes); } } } // remember the processed commithash file_put_contents($startatlock, $commithash); }
require_login(SITEID, false); require_capability('local/amos:execute', get_system_context()); require_capability('local/amos:stage', get_system_context()); $PAGE->set_pagelayout('standard'); $PAGE->set_url('/local/amos/execute.php'); navigation_node::override_active_url(new moodle_url('/local/amos/stage.php')); $PAGE->set_title('AMOS ' . get_string('scriptexecute', 'local_amos')); $PAGE->set_heading('AMOS ' . get_string('scriptexecute', 'local_amos')); $executeform = new local_amos_execute_form(null, local_amos_execute_options()); if ($data = $executeform->get_data()) { $version = mlang_version::by_code($data->version); $stage = mlang_persistent_stage::instance_for_user($USER->id, sesskey()); $instructions = mlang_tools::extract_script_from_text($data->script); if (!empty($instructions)) { foreach ($instructions as $instruction) { $changes = mlang_tools::execute($instruction, $version); if ($changes instanceof mlang_stage) { foreach ($changes->get_iterator() as $component) { $stage->add($component, true); } $changes->clear(); } elseif ($changes < 0) { throw new moodle_exception('error_during_amoscript_execution', 'local_amos', '', null, $changes); } unset($changes); } } $stage->rebase(); $stage->store(); if (!isset($SESSION->local_amos)) { $SESSION->local_amos = new stdClass();
public function test_execution_strings_move() { $stage = new mlang_stage(); $version = mlang_version::by_branch('MOODLE_20_STABLE'); $now = time(); // this block emulates parse-core.php $component = new mlang_component('admin', 'en', $version); $component->add_string(new mlang_string('configsitepolicy', 'OLD', $now - 2)); $stage->add($component); $stage->rebase($now - 2, true, $now - 2); $stage->commit('Committed initial English string', array('source' => 'unittest'), true, $now - 2); $component->clear(); unset($component); // this block emulates parse-lang.php $component = new mlang_component('admin', 'cs', $version); $component->add_string(new mlang_string('configsitepolicy', 'OLD in cs', $now - 1)); $stage->add($component); $stage->rebase(); $stage->commit('Committed initial Czech translation', array('source' => 'unittest'), true, $now - 1); $component->clear(); unset($component); // this block emulates parse-core.php again later // now the string is moved in the English pack by the developer who provides AMOS script in commit message // this happened in b593d49d593ee778f525b4074f5ee7978c5e2960 $component = new mlang_component('admin', 'en', $version); $component->add_string(new mlang_string('sitepolicy_help', 'NEW', $now)); $component->add_string(new mlang_string('configsitepolicy', 'OLD', $now, true)); $commitmsg = 'MDL-24570 multiple sitepolicy fixes + adding new separate guest user policy AMOS BEGIN MOV [configsitepolicy,core_admin],[sitepolicy_help,core_admin] AMOS END'; $stage->add($component); $stage->rebase($now, true, $now); $stage->commit($commitmsg, array('source' => 'unittest'), true, $now); $component->clear(); unset($component); // execute AMOS script if the commit message contains some if ($version->code >= mlang_version::MOODLE_20) { $instructions = mlang_tools::extract_script_from_text($commitmsg); if (!empty($instructions)) { foreach ($instructions as $instruction) { $changes = mlang_tools::execute($instruction, $version, $now); $changes->rebase($now); $changes->commit($commitmsg, array('source' => 'commitscript'), true, $now); unset($changes); } } } // check the results $component = mlang_component::from_snapshot('admin', 'cs', $version, $now); $this->assertTrue($component->has_string('sitepolicy_help')); $this->assertEqual('OLD in cs', $component->get_string('sitepolicy_help')->text); $this->assertEqual(1, $component->get_number_of_strings()); }