Completed
Push — stable12 ( af4951...da6cac )
by Morris
149:33 queued 127:20
created
apps/files/lib/Command/TransferOwnership.php 2 patches
Indentation   +245 added lines, -245 removed lines patch added patch discarded remove patch
@@ -46,249 +46,249 @@
 block discarded – undo
46 46
 
47 47
 class TransferOwnership extends Command {
48 48
 
49
-	/** @var IUserManager $userManager */
50
-	private $userManager;
51
-
52
-	/** @var IManager */
53
-	private $shareManager;
54
-
55
-	/** @var IMountManager */
56
-	private $mountManager;
57
-
58
-	/** @var FileInfo[] */
59
-	private $allFiles = [];
60
-
61
-	/** @var FileInfo[] */
62
-	private $encryptedFiles = [];
63
-
64
-	/** @var IShare[] */
65
-	private $shares = [];
66
-
67
-	/** @var string */
68
-	private $sourceUser;
69
-
70
-	/** @var string */
71
-	private $destinationUser;
72
-
73
-	/** @var string */
74
-	private $sourcePath;
75
-
76
-	/** @var string */
77
-	private $finalTarget;
78
-
79
-	public function __construct(IUserManager $userManager, IManager $shareManager, IMountManager $mountManager) {
80
-		$this->userManager = $userManager;
81
-		$this->shareManager = $shareManager;
82
-		$this->mountManager = $mountManager;
83
-		parent::__construct();
84
-	}
85
-
86
-	protected function configure() {
87
-		$this
88
-			->setName('files:transfer-ownership')
89
-			->setDescription('All files and folders are moved to another user - shares are moved as well.')
90
-			->addArgument(
91
-				'source-user',
92
-				InputArgument::REQUIRED,
93
-				'owner of files which shall be moved'
94
-			)
95
-			->addArgument(
96
-				'destination-user',
97
-				InputArgument::REQUIRED,
98
-				'user who will be the new owner of the files'
99
-			)
100
-			->addOption(
101
-				'path',
102
-				null,
103
-				InputOption::VALUE_REQUIRED,
104
-				'selectively provide the path to transfer. For example --path="folder_name"',
105
-				''
106
-			);
107
-	}
108
-
109
-	protected function execute(InputInterface $input, OutputInterface $output) {
110
-		$sourceUserObject = $this->userManager->get($input->getArgument('source-user'));
111
-		$destinationUserObject = $this->userManager->get($input->getArgument('destination-user'));
112
-
113
-		if (!$sourceUserObject instanceof IUser) {
114
-			$output->writeln("<error>Unknown source user $this->sourceUser</error>");
115
-			return 1;
116
-		}
117
-
118
-		if (!$destinationUserObject instanceof IUser) {
119
-			$output->writeln("<error>Unknown destination user $this->destinationUser</error>");
120
-			return 1;
121
-		}
122
-
123
-		$this->sourceUser = $sourceUserObject->getUID();
124
-		$this->destinationUser = $destinationUserObject->getUID();
125
-		$sourcePathOption = ltrim($input->getOption('path'), '/');
126
-		$this->sourcePath = rtrim($this->sourceUser . '/files/' . $sourcePathOption, '/');
127
-
128
-		// target user has to be ready
129
-		if (!\OC::$server->getEncryptionManager()->isReadyForUser($this->destinationUser)) {
130
-			$output->writeln("<error>The target user is not ready to accept files. The user has at least to be logged in once.</error>");
131
-			return 2;
132
-		}
133
-
134
-		$date = date('Y-m-d H-i-s');
135
-		$this->finalTarget = "$this->destinationUser/files/transferred from $this->sourceUser on $date";
136
-
137
-		// setup filesystem
138
-		Filesystem::initMountPoints($this->sourceUser);
139
-		Filesystem::initMountPoints($this->destinationUser);
140
-
141
-		$view = new View();
142
-		if (!$view->is_dir($this->sourcePath)) {
143
-			$output->writeln("<error>Unknown path provided: $sourcePathOption</error>");
144
-			return 1;
145
-		}
146
-
147
-		// analyse source folder
148
-		$this->analyse($output);
149
-
150
-		// collect all the shares
151
-		$this->collectUsersShares($output);
152
-
153
-		// transfer the files
154
-		$this->transfer($output);
155
-
156
-		// restore the shares
157
-		$this->restoreShares($output);
158
-	}
159
-
160
-	private function walkFiles(View $view, $path, \Closure $callBack) {
161
-		foreach ($view->getDirectoryContent($path) as $fileInfo) {
162
-			if (!$callBack($fileInfo)) {
163
-				return;
164
-			}
165
-			if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
166
-				$this->walkFiles($view, $fileInfo->getPath(), $callBack);
167
-			}
168
-		}
169
-	}
170
-
171
-	/**
172
-	 * @param OutputInterface $output
173
-	 * @throws \Exception
174
-	 */
175
-	protected function analyse(OutputInterface $output) {
176
-		$view = new View();
177
-		$output->writeln("Analysing files of $this->sourceUser ...");
178
-		$progress = new ProgressBar($output);
179
-		$progress->start();
180
-		$self = $this;
181
-
182
-		$this->walkFiles($view, $this->sourcePath,
183
-				function (FileInfo $fileInfo) use ($progress, $self) {
184
-					if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
185
-						// only analyze into folders from main storage,
186
-						if (!$fileInfo->getStorage()->instanceOfStorage(IHomeStorage::class)) {
187
-							return false;
188
-						}
189
-						return true;
190
-					}
191
-					$progress->advance();
192
-					$this->allFiles[] = $fileInfo;
193
-					if ($fileInfo->isEncrypted()) {
194
-						$this->encryptedFiles[] = $fileInfo;
195
-					}
196
-					return true;
197
-				});
198
-		$progress->finish();
199
-		$output->writeln('');
200
-
201
-		// no file is allowed to be encrypted
202
-		if (!empty($this->encryptedFiles)) {
203
-			$output->writeln("<error>Some files are encrypted - please decrypt them first</error>");
204
-			foreach($this->encryptedFiles as $encryptedFile) {
205
-				/** @var FileInfo $encryptedFile */
206
-				$output->writeln("  " . $encryptedFile->getPath());
207
-			}
208
-			throw new \Exception('Execution terminated.');
209
-		}
210
-
211
-	}
212
-
213
-	/**
214
-	 * @param OutputInterface $output
215
-	 */
216
-	private function collectUsersShares(OutputInterface $output) {
217
-		$output->writeln("Collecting all share information for files and folder of $this->sourceUser ...");
218
-
219
-		$progress = new ProgressBar($output, count($this->shares));
220
-		foreach([\OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE] as $shareType) {
221
-		$offset = 0;
222
-			while (true) {
223
-				$sharePage = $this->shareManager->getSharesBy($this->sourceUser, $shareType, null, true, 50, $offset);
224
-				$progress->advance(count($sharePage));
225
-				if (empty($sharePage)) {
226
-					break;
227
-				}
228
-				$this->shares = array_merge($this->shares, $sharePage);
229
-				$offset += 50;
230
-			}
231
-		}
232
-
233
-		$progress->finish();
234
-		$output->writeln('');
235
-	}
236
-
237
-	/**
238
-	 * @param OutputInterface $output
239
-	 */
240
-	protected function transfer(OutputInterface $output) {
241
-		$view = new View();
242
-		$output->writeln("Transferring files to $this->finalTarget ...");
243
-
244
-		// This change will help user to transfer the folder specified using --path option.
245
-		// Else only the content inside folder is transferred which is not correct.
246
-		if($this->sourcePath !== "$this->sourceUser/files") {
247
-			$view->mkdir($this->finalTarget);
248
-			$this->finalTarget = $this->finalTarget . '/' . basename($this->sourcePath);
249
-		}
250
-		$view->rename($this->sourcePath, $this->finalTarget);
251
-		if (!is_dir("$this->sourceUser/files")) {
252
-			// because the files folder is moved away we need to recreate it
253
-			$view->mkdir("$this->sourceUser/files");
254
-		}
255
-	}
256
-
257
-	/**
258
-	 * @param OutputInterface $output
259
-	 */
260
-	private function restoreShares(OutputInterface $output) {
261
-		$output->writeln("Restoring shares ...");
262
-		$progress = new ProgressBar($output, count($this->shares));
263
-
264
-		foreach($this->shares as $share) {
265
-			try {
266
-				if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
267
-						$share->getSharedWith() === $this->destinationUser) {
268
-					// Unmount the shares before deleting, so we don't try to get the storage later on.
269
-					$shareMountPoint = $this->mountManager->find('/' . $this->destinationUser . '/files' . $share->getTarget());
270
-					if ($shareMountPoint) {
271
-						$this->mountManager->removeMount($shareMountPoint->getMountPoint());
272
-					}
273
-					$this->shareManager->deleteShare($share);
274
-				} else {
275
-					if ($share->getShareOwner() === $this->sourceUser) {
276
-						$share->setShareOwner($this->destinationUser);
277
-					}
278
-					if ($share->getSharedBy() === $this->sourceUser) {
279
-						$share->setSharedBy($this->destinationUser);
280
-					}
281
-
282
-					$this->shareManager->updateShare($share);
283
-				}
284
-			} catch (\OCP\Files\NotFoundException $e) {
285
-				$output->writeln('<error>Share with id ' . $share->getId() . ' points at deleted file, skipping</error>');
286
-			} catch (\Exception $e) {
287
-				$output->writeln('<error>Could not restore share with id ' . $share->getId() . ':' . $e->getTraceAsString() . '</error>');
288
-			}
289
-			$progress->advance();
290
-		}
291
-		$progress->finish();
292
-		$output->writeln('');
293
-	}
49
+    /** @var IUserManager $userManager */
50
+    private $userManager;
51
+
52
+    /** @var IManager */
53
+    private $shareManager;
54
+
55
+    /** @var IMountManager */
56
+    private $mountManager;
57
+
58
+    /** @var FileInfo[] */
59
+    private $allFiles = [];
60
+
61
+    /** @var FileInfo[] */
62
+    private $encryptedFiles = [];
63
+
64
+    /** @var IShare[] */
65
+    private $shares = [];
66
+
67
+    /** @var string */
68
+    private $sourceUser;
69
+
70
+    /** @var string */
71
+    private $destinationUser;
72
+
73
+    /** @var string */
74
+    private $sourcePath;
75
+
76
+    /** @var string */
77
+    private $finalTarget;
78
+
79
+    public function __construct(IUserManager $userManager, IManager $shareManager, IMountManager $mountManager) {
80
+        $this->userManager = $userManager;
81
+        $this->shareManager = $shareManager;
82
+        $this->mountManager = $mountManager;
83
+        parent::__construct();
84
+    }
85
+
86
+    protected function configure() {
87
+        $this
88
+            ->setName('files:transfer-ownership')
89
+            ->setDescription('All files and folders are moved to another user - shares are moved as well.')
90
+            ->addArgument(
91
+                'source-user',
92
+                InputArgument::REQUIRED,
93
+                'owner of files which shall be moved'
94
+            )
95
+            ->addArgument(
96
+                'destination-user',
97
+                InputArgument::REQUIRED,
98
+                'user who will be the new owner of the files'
99
+            )
100
+            ->addOption(
101
+                'path',
102
+                null,
103
+                InputOption::VALUE_REQUIRED,
104
+                'selectively provide the path to transfer. For example --path="folder_name"',
105
+                ''
106
+            );
107
+    }
108
+
109
+    protected function execute(InputInterface $input, OutputInterface $output) {
110
+        $sourceUserObject = $this->userManager->get($input->getArgument('source-user'));
111
+        $destinationUserObject = $this->userManager->get($input->getArgument('destination-user'));
112
+
113
+        if (!$sourceUserObject instanceof IUser) {
114
+            $output->writeln("<error>Unknown source user $this->sourceUser</error>");
115
+            return 1;
116
+        }
117
+
118
+        if (!$destinationUserObject instanceof IUser) {
119
+            $output->writeln("<error>Unknown destination user $this->destinationUser</error>");
120
+            return 1;
121
+        }
122
+
123
+        $this->sourceUser = $sourceUserObject->getUID();
124
+        $this->destinationUser = $destinationUserObject->getUID();
125
+        $sourcePathOption = ltrim($input->getOption('path'), '/');
126
+        $this->sourcePath = rtrim($this->sourceUser . '/files/' . $sourcePathOption, '/');
127
+
128
+        // target user has to be ready
129
+        if (!\OC::$server->getEncryptionManager()->isReadyForUser($this->destinationUser)) {
130
+            $output->writeln("<error>The target user is not ready to accept files. The user has at least to be logged in once.</error>");
131
+            return 2;
132
+        }
133
+
134
+        $date = date('Y-m-d H-i-s');
135
+        $this->finalTarget = "$this->destinationUser/files/transferred from $this->sourceUser on $date";
136
+
137
+        // setup filesystem
138
+        Filesystem::initMountPoints($this->sourceUser);
139
+        Filesystem::initMountPoints($this->destinationUser);
140
+
141
+        $view = new View();
142
+        if (!$view->is_dir($this->sourcePath)) {
143
+            $output->writeln("<error>Unknown path provided: $sourcePathOption</error>");
144
+            return 1;
145
+        }
146
+
147
+        // analyse source folder
148
+        $this->analyse($output);
149
+
150
+        // collect all the shares
151
+        $this->collectUsersShares($output);
152
+
153
+        // transfer the files
154
+        $this->transfer($output);
155
+
156
+        // restore the shares
157
+        $this->restoreShares($output);
158
+    }
159
+
160
+    private function walkFiles(View $view, $path, \Closure $callBack) {
161
+        foreach ($view->getDirectoryContent($path) as $fileInfo) {
162
+            if (!$callBack($fileInfo)) {
163
+                return;
164
+            }
165
+            if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
166
+                $this->walkFiles($view, $fileInfo->getPath(), $callBack);
167
+            }
168
+        }
169
+    }
170
+
171
+    /**
172
+     * @param OutputInterface $output
173
+     * @throws \Exception
174
+     */
175
+    protected function analyse(OutputInterface $output) {
176
+        $view = new View();
177
+        $output->writeln("Analysing files of $this->sourceUser ...");
178
+        $progress = new ProgressBar($output);
179
+        $progress->start();
180
+        $self = $this;
181
+
182
+        $this->walkFiles($view, $this->sourcePath,
183
+                function (FileInfo $fileInfo) use ($progress, $self) {
184
+                    if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
185
+                        // only analyze into folders from main storage,
186
+                        if (!$fileInfo->getStorage()->instanceOfStorage(IHomeStorage::class)) {
187
+                            return false;
188
+                        }
189
+                        return true;
190
+                    }
191
+                    $progress->advance();
192
+                    $this->allFiles[] = $fileInfo;
193
+                    if ($fileInfo->isEncrypted()) {
194
+                        $this->encryptedFiles[] = $fileInfo;
195
+                    }
196
+                    return true;
197
+                });
198
+        $progress->finish();
199
+        $output->writeln('');
200
+
201
+        // no file is allowed to be encrypted
202
+        if (!empty($this->encryptedFiles)) {
203
+            $output->writeln("<error>Some files are encrypted - please decrypt them first</error>");
204
+            foreach($this->encryptedFiles as $encryptedFile) {
205
+                /** @var FileInfo $encryptedFile */
206
+                $output->writeln("  " . $encryptedFile->getPath());
207
+            }
208
+            throw new \Exception('Execution terminated.');
209
+        }
210
+
211
+    }
212
+
213
+    /**
214
+     * @param OutputInterface $output
215
+     */
216
+    private function collectUsersShares(OutputInterface $output) {
217
+        $output->writeln("Collecting all share information for files and folder of $this->sourceUser ...");
218
+
219
+        $progress = new ProgressBar($output, count($this->shares));
220
+        foreach([\OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE] as $shareType) {
221
+        $offset = 0;
222
+            while (true) {
223
+                $sharePage = $this->shareManager->getSharesBy($this->sourceUser, $shareType, null, true, 50, $offset);
224
+                $progress->advance(count($sharePage));
225
+                if (empty($sharePage)) {
226
+                    break;
227
+                }
228
+                $this->shares = array_merge($this->shares, $sharePage);
229
+                $offset += 50;
230
+            }
231
+        }
232
+
233
+        $progress->finish();
234
+        $output->writeln('');
235
+    }
236
+
237
+    /**
238
+     * @param OutputInterface $output
239
+     */
240
+    protected function transfer(OutputInterface $output) {
241
+        $view = new View();
242
+        $output->writeln("Transferring files to $this->finalTarget ...");
243
+
244
+        // This change will help user to transfer the folder specified using --path option.
245
+        // Else only the content inside folder is transferred which is not correct.
246
+        if($this->sourcePath !== "$this->sourceUser/files") {
247
+            $view->mkdir($this->finalTarget);
248
+            $this->finalTarget = $this->finalTarget . '/' . basename($this->sourcePath);
249
+        }
250
+        $view->rename($this->sourcePath, $this->finalTarget);
251
+        if (!is_dir("$this->sourceUser/files")) {
252
+            // because the files folder is moved away we need to recreate it
253
+            $view->mkdir("$this->sourceUser/files");
254
+        }
255
+    }
256
+
257
+    /**
258
+     * @param OutputInterface $output
259
+     */
260
+    private function restoreShares(OutputInterface $output) {
261
+        $output->writeln("Restoring shares ...");
262
+        $progress = new ProgressBar($output, count($this->shares));
263
+
264
+        foreach($this->shares as $share) {
265
+            try {
266
+                if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
267
+                        $share->getSharedWith() === $this->destinationUser) {
268
+                    // Unmount the shares before deleting, so we don't try to get the storage later on.
269
+                    $shareMountPoint = $this->mountManager->find('/' . $this->destinationUser . '/files' . $share->getTarget());
270
+                    if ($shareMountPoint) {
271
+                        $this->mountManager->removeMount($shareMountPoint->getMountPoint());
272
+                    }
273
+                    $this->shareManager->deleteShare($share);
274
+                } else {
275
+                    if ($share->getShareOwner() === $this->sourceUser) {
276
+                        $share->setShareOwner($this->destinationUser);
277
+                    }
278
+                    if ($share->getSharedBy() === $this->sourceUser) {
279
+                        $share->setSharedBy($this->destinationUser);
280
+                    }
281
+
282
+                    $this->shareManager->updateShare($share);
283
+                }
284
+            } catch (\OCP\Files\NotFoundException $e) {
285
+                $output->writeln('<error>Share with id ' . $share->getId() . ' points at deleted file, skipping</error>');
286
+            } catch (\Exception $e) {
287
+                $output->writeln('<error>Could not restore share with id ' . $share->getId() . ':' . $e->getTraceAsString() . '</error>');
288
+            }
289
+            $progress->advance();
290
+        }
291
+        $progress->finish();
292
+        $output->writeln('');
293
+    }
294 294
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -123,7 +123,7 @@  discard block
 block discarded – undo
123 123
 		$this->sourceUser = $sourceUserObject->getUID();
124 124
 		$this->destinationUser = $destinationUserObject->getUID();
125 125
 		$sourcePathOption = ltrim($input->getOption('path'), '/');
126
-		$this->sourcePath = rtrim($this->sourceUser . '/files/' . $sourcePathOption, '/');
126
+		$this->sourcePath = rtrim($this->sourceUser.'/files/'.$sourcePathOption, '/');
127 127
 
128 128
 		// target user has to be ready
129 129
 		if (!\OC::$server->getEncryptionManager()->isReadyForUser($this->destinationUser)) {
@@ -180,7 +180,7 @@  discard block
 block discarded – undo
180 180
 		$self = $this;
181 181
 
182 182
 		$this->walkFiles($view, $this->sourcePath,
183
-				function (FileInfo $fileInfo) use ($progress, $self) {
183
+				function(FileInfo $fileInfo) use ($progress, $self) {
184 184
 					if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
185 185
 						// only analyze into folders from main storage,
186 186
 						if (!$fileInfo->getStorage()->instanceOfStorage(IHomeStorage::class)) {
@@ -201,9 +201,9 @@  discard block
 block discarded – undo
201 201
 		// no file is allowed to be encrypted
202 202
 		if (!empty($this->encryptedFiles)) {
203 203
 			$output->writeln("<error>Some files are encrypted - please decrypt them first</error>");
204
-			foreach($this->encryptedFiles as $encryptedFile) {
204
+			foreach ($this->encryptedFiles as $encryptedFile) {
205 205
 				/** @var FileInfo $encryptedFile */
206
-				$output->writeln("  " . $encryptedFile->getPath());
206
+				$output->writeln("  ".$encryptedFile->getPath());
207 207
 			}
208 208
 			throw new \Exception('Execution terminated.');
209 209
 		}
@@ -217,7 +217,7 @@  discard block
 block discarded – undo
217 217
 		$output->writeln("Collecting all share information for files and folder of $this->sourceUser ...");
218 218
 
219 219
 		$progress = new ProgressBar($output, count($this->shares));
220
-		foreach([\OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE] as $shareType) {
220
+		foreach ([\OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE] as $shareType) {
221 221
 		$offset = 0;
222 222
 			while (true) {
223 223
 				$sharePage = $this->shareManager->getSharesBy($this->sourceUser, $shareType, null, true, 50, $offset);
@@ -243,9 +243,9 @@  discard block
 block discarded – undo
243 243
 
244 244
 		// This change will help user to transfer the folder specified using --path option.
245 245
 		// Else only the content inside folder is transferred which is not correct.
246
-		if($this->sourcePath !== "$this->sourceUser/files") {
246
+		if ($this->sourcePath !== "$this->sourceUser/files") {
247 247
 			$view->mkdir($this->finalTarget);
248
-			$this->finalTarget = $this->finalTarget . '/' . basename($this->sourcePath);
248
+			$this->finalTarget = $this->finalTarget.'/'.basename($this->sourcePath);
249 249
 		}
250 250
 		$view->rename($this->sourcePath, $this->finalTarget);
251 251
 		if (!is_dir("$this->sourceUser/files")) {
@@ -261,12 +261,12 @@  discard block
 block discarded – undo
261 261
 		$output->writeln("Restoring shares ...");
262 262
 		$progress = new ProgressBar($output, count($this->shares));
263 263
 
264
-		foreach($this->shares as $share) {
264
+		foreach ($this->shares as $share) {
265 265
 			try {
266 266
 				if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
267 267
 						$share->getSharedWith() === $this->destinationUser) {
268 268
 					// Unmount the shares before deleting, so we don't try to get the storage later on.
269
-					$shareMountPoint = $this->mountManager->find('/' . $this->destinationUser . '/files' . $share->getTarget());
269
+					$shareMountPoint = $this->mountManager->find('/'.$this->destinationUser.'/files'.$share->getTarget());
270 270
 					if ($shareMountPoint) {
271 271
 						$this->mountManager->removeMount($shareMountPoint->getMountPoint());
272 272
 					}
@@ -282,9 +282,9 @@  discard block
 block discarded – undo
282 282
 					$this->shareManager->updateShare($share);
283 283
 				}
284 284
 			} catch (\OCP\Files\NotFoundException $e) {
285
-				$output->writeln('<error>Share with id ' . $share->getId() . ' points at deleted file, skipping</error>');
285
+				$output->writeln('<error>Share with id '.$share->getId().' points at deleted file, skipping</error>');
286 286
 			} catch (\Exception $e) {
287
-				$output->writeln('<error>Could not restore share with id ' . $share->getId() . ':' . $e->getTraceAsString() . '</error>');
287
+				$output->writeln('<error>Could not restore share with id '.$share->getId().':'.$e->getTraceAsString().'</error>');
288 288
 			}
289 289
 			$progress->advance();
290 290
 		}
Please login to merge, or discard this patch.