public function get_tag_rev($file, $tag) { $sth = dbh_query_bind("SELECT revision FROM file_tag WHERE file = ? AND tag = ?", $file, $tag); $row = $sth->fetch(PDO::FETCH_NUM); $sth->closeCursor(); $tag_rev = null; if (!empty($row)) { list($tag_rev) = $row; } return $tag_rev; }
public function updateEntireRepoAction($tag, $user) { set_time_limit(0); $cmd = ''; $command_output = ''; ### Prepare for a MASS HEAD update if updating to HEAD $doing_indiv_dir_update = array(); if ($tag == 'HEAD') { $head_update_cmd = "svn update"; START_TIMER('REPO_CMD', PROJECT_PROJECT_TIMERS); $this->log_repo_action($head_update_cmd, 'entire_repo', $user); $command_output .= shell_exec($this->stage->config('repo_cmd_prefix') . "{$head_update_cmd} 2>&1 | cat -"); END_TIMER('REPO_CMD', PROJECT_PROJECT_TIMERS); $cmd .= "\n" . (strlen($cmd) ? ' ; ' : '') . $head_update_cmd; } else { ############################# ### Step 1 : First find any files that we have tags for but don't exist ### Start out by updating all rows in the tag table as mass_edit=1 ### as we delete and update, the ones that have tags will be set back to 0 $rv = dbh_do_bind("UPDATE file_tag SET mass_edit=1 AND tag=?", $tag); $command_output = ''; $status = $this->get_dir_status(); foreach (preg_split('/\\n/', $status) as $line) { if (preg_match('/^\\s*[A-Z]?\\s*\\d+\\s+(\\d+)\\s+\\S+\\s+(\\S.*)$/', $line, $m)) { $cur_rev = $m[1]; $file = rtrim($m[2], "\n\r"); /// Override this with the SLOW, but accurate alternate. This turns a 2 min update into a 2+ hour update list($cur_rev) = $this->get_current_rev($file); ### Skip dirs in SVN (for now)... if (is_dir($this->stage->env()->repo_base . '/' . $file)) { continue; } ### We could be cache-ing the tags here, but in some repos with long file paths and hundreds of thousands of files, we would run out of memory # ### See what the tag is... # $sth = dbh_query_bind("SELECT revision FROM file_tag WHERE file = ? AND tag = ?", $file, $tag); # $old_rev = $sth->fetch(PDO::FETCH_NUM); # $sth->closeCursor(); ### ALL we are doing for the files that exist for this loop is marking mass_edit as off $rv = dbh_do_bind("UPDATE file_tag SET mass_edit=0 WHERE file = ? AND tag = ?", $file, $tag); } } ############################# ### Step 2 : Update the files that didn't exist... ### The rows the mass_edit still need to be Un-tagged... ### See what the tag was before... $sth = dbh_query_bind("SELECT file,revision FROM file_tag WHERE mass_edit=1 AND tag=?", $tag); while (list($file, $rev) = $sth->fetch(PDO::FETCH_NUM)) { /// Each loop, do a $individual_file_rev_updates instead of globally $individual_file_rev_updates = array(); $dir_test = $file; ### Before we do Inidividual Tag updates on files the containing dirs must exist $dirs_to_update = array(); while (!empty($dir_test) && !is_dir(dirname($this->stage->env()->repo_base . "/{$dir_test}")) && $this->stage->env()->repo_base != dirname($this->stage->env()->repo_base . "/{$dir_test}") && !array_key_exists(dirname($dir_test), $doing_indiv_dir_update)) { $dir = dirname($dir_test); $dirs_to_update[] = $dir; $doing_indiv_dir_update[$dir] = true; $dir_test = $dir; // iterate backwards } /// Need to add in parent-first order /// NOTE: we only need to do the parent one, because the in-between ones will be included if (count($dirs_to_update)) { $individual_file_rev_updates[] = array(array_pop($dirs_to_update), $rev); } $individual_file_rev_updates[] = array($file, $rev); foreach ($individual_file_rev_updates as $update) { list($up_file, $up_rev) = $update; $indiv_update_cmd = "svn update -r{$up_rev} " . escapeshellcmd($up_file); START_TIMER('REPO_CMD', PROJECT_PROJECT_TIMERS); $this->log_repo_action($indiv_update_cmd, 'entire_repo', $user); $command_output .= shell_exec($this->stage->config('repo_cmd_prefix') . "{$indiv_update_cmd} 2>&1 | cat -"); END_TIMER('REPO_CMD', PROJECT_PROJECT_TIMERS); $cmd .= "\n" . (strlen($cmd) ? ' ; ' : '') . $indiv_update_cmd; } } $sth->closeCursor(); $rv = dbh_do_bind("UPDATE file_tag SET mass_edit=0 WHERE tag=?", $tag); ############################# ### Step 3 : NOW, get a new Status output, and go through again, now that all files are present and set everything to the right tags ### Reset Cache on dir status unset($this->repo_cache['dir_status']['*ROOTDIR*']); $status = $this->get_dir_status(); foreach (preg_split('/\\n/', $status) as $line) { if (preg_match('/^\\s*[A-Z]?\\s*\\d+\\s+(\\d+)\\s+\\S+\\s+(\\S.*)$/', $line, $m)) { $cur_rev = $m[1]; $file = rtrim($m[2], "\n\r"); if (is_dir($this->stage->env()->repo_base . "/{$file}")) { continue; } /// Each loop, do a $individual_file_rev_updates instead of globally $individual_file_rev_updates = array(); ### Get the tag rev for this file... $sth = dbh_query_bind("SELECT revision FROM file_tag WHERE file = ? AND tag = ?", $file, $tag); $rev = $sth->fetch(PDO::FETCH_NUM); $sth->closeCursor(); if (!empty($rev)) { $dir_test = $file; ### Before we do Inidividual Tag updates on files the containing dirs must exist $dirs_to_update = array(); while (!empty($dir_test) && !is_dir(dirname($this->stage->env()->repo_base . "/{$dir_test}")) && $this->stage->env()->repo_base != dirname($this->stage->env()->repo_base . "/{$dir_test}") && !array_key_exists(dirname($dir_test), $doing_indiv_dir_update)) { $dir = dirname($dir_test); $dirs_to_update[] = $dir; $doing_indiv_dir_update[$dir] = true; $dir_test = $dir; // iterate backwards } /// Need to add in parent-first order /// NOTE: we only need to do the parent one, because the in-between ones will be included if (count($dirs_to_update)) { # bug("Parent Dir update", $file); $individual_file_rev_updates[] = array(array_pop($dirs_to_update), $rev[0]); } else { if ($cur_rev != $rev[0]) { # bug("Regular update", $file); $individual_file_rev_updates[] = array($file, $rev[0]); } } } else { list($first_rev, $error) = $this->get_first_rev($file); # bug("NO TAG, intent-to-rm update", $file, $first_rev); if (empty($error)) { $rev_before_first = $first_rev - 1; $individual_file_rev_updates[] = array($file, $rev_before_first); } } /// Do updates... foreach ($individual_file_rev_updates as $update) { list($up_file, $up_rev) = $update; $indiv_update_cmd = "svn update -r{$up_rev} " . escapeshellcmd($up_file); START_TIMER('REPO_CMD', PROJECT_PROJECT_TIMERS); $this->log_repo_action($indiv_update_cmd, 'entire_repo', $user); $command_output .= shell_exec($this->stage->config('repo_cmd_prefix') . "{$indiv_update_cmd} 2>&1 | cat -"); END_TIMER('REPO_CMD', PROJECT_PROJECT_TIMERS); $cmd .= "\n" . (strlen($cmd) ? ' ; ' : '') . $indiv_update_cmd; } } } } if (empty($command_output)) { $command_output = '</xmp><i>No output</i>'; } return array($cmd, $command_output); }