@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhabricatorRepositoryManagementMovePathsWorkflow
4 extends PhabricatorRepositoryManagementWorkflow {
5
6 protected function didConstruct() {
7 $this
8 ->setName('move-paths')
9 ->setSynopsis(pht('Move repository local paths.'))
10 ->setArguments(
11 array(
12 array(
13 'name' => 'from',
14 'param' => 'prefix',
15 'help' => pht('Move paths with this prefix.'),
16 ),
17 array(
18 'name' => 'to',
19 'param' => 'prefix',
20 'help' => pht('Replace matching prefixes with this string.'),
21 ),
22 array(
23 'name' => 'force',
24 'help' => pht('Apply changes without prompting.'),
25 ),
26 ));
27 }
28
29 public function execute(PhutilArgumentParser $args) {
30 $console = PhutilConsole::getConsole();
31
32 $repos = id(new PhabricatorRepositoryQuery())
33 ->setViewer($this->getViewer())
34 ->execute();
35 if (!$repos) {
36 $console->writeErr("%s\n", pht('There are no repositories.'));
37 return 0;
38 }
39
40 $from = $args->getArg('from');
41 if (!phutil_nonempty_string($from)) {
42 throw new Exception(
43 pht(
44 'You must specify a path prefix to move from with --from.'));
45 }
46
47 $to = $args->getArg('to');
48 if (!phutil_nonempty_string($to)) {
49 throw new Exception(
50 pht(
51 'You must specify a path prefix to move to with --to.'));
52 }
53
54 $is_force = $args->getArg('force');
55
56 $rows = array();
57
58 $any_changes = false;
59 foreach ($repos as $repo) {
60 $src = $repo->getLocalPath();
61
62 $row = array(
63 'repository' => $repo,
64 'move' => false,
65 'monogram' => $repo->getMonogram(),
66 'src' => $src,
67 'dst' => '',
68 );
69
70 if (strncmp($src, $from, strlen($from))) {
71 $row['action'] = pht('Ignore');
72 } else {
73 $dst = $to.substr($src, strlen($from));
74
75 $row['action'] = tsprintf('**%s**', pht('Move'));
76 $row['dst'] = $dst;
77 $row['move'] = true;
78 $any_changes = true;
79 }
80
81 $rows[] = $row;
82 }
83
84 $table = id(new PhutilConsoleTable())
85 ->addColumn(
86 'action',
87 array(
88 'title' => pht('Action'),
89 ))
90 ->addColumn(
91 'monogram',
92 array(
93 'title' => pht('Repository'),
94 ))
95 ->addColumn(
96 'src',
97 array(
98 'title' => pht('Src'),
99 ))
100 ->addColumn(
101 'dst',
102 array(
103 'title' => pht('Dst'),
104 ))
105 ->setBorders(true);
106
107 foreach ($rows as $row) {
108 $display = array_select_keys(
109 $row,
110 array(
111 'action',
112 'monogram',
113 'src',
114 'dst',
115 ));
116 $table->addRow($display);
117 }
118
119 $table->draw();
120
121 if (!$any_changes) {
122 $console->writeOut(pht('No matching repositories.')."\n");
123 return 0;
124 }
125
126 $prompt = pht('Apply these changes?');
127 if (!$is_force && !phutil_console_confirm($prompt)) {
128 throw new Exception(pht('Declining to apply changes.'));
129 }
130
131 foreach ($rows as $row) {
132 if (empty($row['move'])) {
133 continue;
134 }
135
136 $repo = $row['repository'];
137
138 queryfx(
139 $repo->establishConnection('w'),
140 'UPDATE %T SET localPath = %s WHERE id = %d',
141 $repo->getTableName(),
142 $row['dst'],
143 $repo->getID());
144 }
145
146 $console->writeOut(pht('Applied changes.')."\n");
147 return 0;
148 }
149
150}