37
37
use OC \Core \Command \InterruptedException ;
38
38
use OC \DB \Connection ;
39
39
use OC \DB \ConnectionAdapter ;
40
+ use OC \Files \Filesystem ;
41
+ use OC \Files \Node \File ;
42
+ use OC \Files \Node \Folder ;
43
+ use OC \Files \Node \NonExistingFile ;
44
+ use OC \Files \Node \NonExistingFolder ;
45
+ use OC \Files \View ;
40
46
use OC \ForbiddenException ;
47
+ use OC \Metadata \MetadataManager ;
41
48
use OCP \EventDispatcher \IEventDispatcher ;
49
+ use OCP \Files \FileInfo ;
50
+ use OCP \Files \IRootFolder ;
42
51
use OCP \Files \Mount \IMountPoint ;
43
52
use OCP \Files \NotFoundException ;
44
53
use OCP \Files \StorageNotAvailableException ;
51
60
use Symfony \Component \Console \Output \OutputInterface ;
52
61
53
62
class Scan extends Base {
63
+ private IUserManager $ userManager ;
64
+ protected float $ execTime = 0 ;
65
+ protected int $ foldersCounter = 0 ;
66
+ protected int $ filesCounter = 0 ;
67
+ private IRootFolder $ root ;
68
+ private View $ view ;
54
69
55
- /** @var IUserManager $userManager */
56
- private $ userManager ;
57
- /** @var float */
58
- protected $ execTime = 0 ;
59
- /** @var int */
60
- protected $ foldersCounter = 0 ;
61
- /** @var int */
62
- protected $ filesCounter = 0 ;
63
-
64
- public function __construct (IUserManager $ userManager ) {
70
+ public function __construct (IUserManager $ userManager , IRootFolder $ rootFolder , View $ view ) {
65
71
$ this ->userManager = $ userManager ;
66
72
parent ::__construct ();
73
+ $ this ->root = $ rootFolder ;
74
+ $ this ->view = $ view ;
67
75
}
68
76
69
77
protected function configure () {
@@ -83,6 +91,13 @@ protected function configure() {
83
91
InputArgument::OPTIONAL ,
84
92
'limit rescan to this path, eg. --path="/alice/files/Music", the user_id is determined by the path and the user_id parameter and --all are ignored '
85
93
)
94
+ ->addOption (
95
+ 'metadata ' ,
96
+ null ,
97
+ InputOption::VALUE_NONE ,
98
+ 'Add missing file metadata ' ,
99
+ false
100
+ )
86
101
->addOption (
87
102
'all ' ,
88
103
null ,
@@ -106,21 +121,28 @@ protected function configure() {
106
121
);
107
122
}
108
123
109
- protected function scanFiles ($ user , $ path , OutputInterface $ output , $ backgroundScan = false , $ recursive = true , $ homeOnly = false ) {
124
+ protected function scanFiles ($ user , $ path , bool $ scanMetadata , OutputInterface $ output , $ backgroundScan = false , $ recursive = true , $ homeOnly = false ) {
110
125
$ connection = $ this ->reconnectToDatabase ($ output );
111
126
$ scanner = new \OC \Files \Utils \Scanner (
112
127
$ user ,
113
128
new ConnectionAdapter ($ connection ),
114
- \OC ::$ server ->query (IEventDispatcher::class),
129
+ \OC ::$ server ->get (IEventDispatcher::class),
115
130
\OC ::$ server ->get (LoggerInterface::class)
116
131
);
117
132
118
133
# check on each file/folder if there was a user interrupt (ctrl-c) and throw an exception
119
134
120
- $ scanner ->listen ('\OC\Files\Utils\Scanner ' , 'scanFile ' , function ($ path ) use ($ output ) {
135
+ /** @var MetadataManager $metadataManager */
136
+ $ metadataManager = \OC ::$ server ->get (MetadataManager::class);
137
+
138
+ $ scanner ->listen ('\OC\Files\Utils\Scanner ' , 'scanFile ' , function ($ path ) use ($ output , $ metadataManager , $ scanMetadata ) {
121
139
$ output ->writeln ("\tFile \t<info> $ path</info> " , OutputInterface::VERBOSITY_VERBOSE );
122
140
++$ this ->filesCounter ;
123
141
$ this ->abortIfInterrupted ();
142
+ if ($ scanMetadata ) {
143
+ $ node = $ this ->getNodeForPath ($ path );
144
+ $ metadataManager ->generateMetadata ($ node , true );
145
+ }
124
146
});
125
147
126
148
$ scanner ->listen ('\OC\Files\Utils\Scanner ' , 'scanFolder ' , function ($ path ) use ($ output ) {
@@ -150,7 +172,7 @@ protected function scanFiles($user, $path, OutputInterface $output, $backgroundS
150
172
# exit the function if ctrl-c has been pressed
151
173
$ output ->writeln ('Interrupted by user ' );
152
174
} catch (NotFoundException $ e ) {
153
- $ output ->writeln ('<error>Path not found: ' . $ e ->getMessage () . '</error> ' );
175
+ $ output ->writeln ('<error>Path not found: ' . $ e ->getMessage () . '</error> ' . var_export ( $ e -> getTraceAsString ()) );
154
176
} catch (\Exception $ e ) {
155
177
$ output ->writeln ('<error>Exception during scan: ' . $ e ->getMessage () . '</error> ' );
156
178
$ output ->writeln ('<error> ' . $ e ->getTraceAsString () . '</error> ' );
@@ -197,7 +219,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
197
219
++$ user_count ;
198
220
if ($ this ->userManager ->userExists ($ user )) {
199
221
$ output ->writeln ("Starting scan for user $ user_count out of $ users_total ( $ user) " );
200
- $ this ->scanFiles ($ user , $ path , $ output , $ input ->getOption ('unscanned ' ), !$ input ->getOption ('shallow ' ), $ input ->getOption ('home-only ' ));
222
+ $ this ->scanFiles ($ user , $ path , $ input -> getOption ( ' metadata ' ), $ output , $ input ->getOption ('unscanned ' ), !$ input ->getOption ('shallow ' ), $ input ->getOption ('home-only ' ));
201
223
$ output ->writeln ('' , OutputInterface::VERBOSITY_VERBOSE );
202
224
} else {
203
225
$ output ->writeln ("<error>Unknown user $ user_count $ user</error> " );
@@ -312,4 +334,32 @@ protected function reconnectToDatabase(OutputInterface $output): Connection {
312
334
}
313
335
return $ connection ;
314
336
}
337
+
338
+ private function getNodeForPath ($ path ) {
339
+ $ pathParts = explode ('/ ' , $ path );
340
+ // FIXME ugly hack to get it working for local file
341
+ array_shift ($ pathParts );
342
+ array_shift ($ pathParts );
343
+ array_shift ($ pathParts );
344
+ $ info = Filesystem::getFileInfo ('/ ' . implode ('/ ' , $ pathParts ));
345
+ if (!$ info ) {
346
+ $ fullPath = Filesystem::getView ()->getAbsolutePath ($ path );
347
+ if (isset ($ this ->deleteMetaCache [$ fullPath ])) {
348
+ $ info = $ this ->deleteMetaCache [$ fullPath ];
349
+ } else {
350
+ $ info = null ;
351
+ }
352
+ if (Filesystem::is_dir ($ path )) {
353
+ return new NonExistingFolder ($ this ->root , $ this ->view , $ fullPath , $ info );
354
+ } else {
355
+ return new NonExistingFile ($ this ->root , $ this ->view , $ fullPath , $ info );
356
+ }
357
+ }
358
+ if ($ info ->getType () === FileInfo::TYPE_FILE ) {
359
+ return new File ($ this ->root , $ this ->view , $ info ->getPath (), $ info );
360
+ } else {
361
+ return new Folder ($ this ->root , $ this ->view , $ info ->getPath (), $ info );
362
+ }
363
+ }
364
+
315
365
}
0 commit comments