diff --git a/slave/buildslave/commands/fs.py b/slave/buildslave/commands/fs.py index 9f7d04198ac..44aa0614e2c 100644 --- a/slave/buildslave/commands/fs.py +++ b/slave/buildslave/commands/fs.py @@ -193,3 +193,28 @@ def start(self): # always set the RC, regardless of platform d.addCallbacks(self._sendRC, self._checkAbandoned) return d + +class StatFile(base.Command): + """This is a command which stats a file on the slave. The args dict contains the following keys: + + - ['file'] (required): file to stat + + StatFile creates the following status messages: + - {'rc': rc} : 0 if the file is found, 1 otherwise + - {'stat': stat} : if the files is found, stat contains the result of os.stat + """ + + header = "stat" + + def start(self): + args = self.args + # args['dir'] is relative to Builder directory, and is required. + assert args['file'] is not None + filename = os.path.join(self.builder.basedir, args['file']) + + try: + stat = os.stat(filename) + self.sendStatus({'stat': tuple(stat)}) + self.sendStatus({'rc': 0}) + except: + self.sendStatus({'rc': 1}) diff --git a/slave/buildslave/commands/registry.py b/slave/buildslave/commands/registry.py index 0cf057194a5..b5f37563dfe 100644 --- a/slave/buildslave/commands/registry.py +++ b/slave/buildslave/commands/registry.py @@ -34,6 +34,7 @@ "mkdir" : "buildslave.commands.fs.MakeDirectory", "rmdir" : "buildslave.commands.fs.RemoveDirectory", "cpdir" : "buildslave.commands.fs.CopyDirectory", + "stat" : "buildslave.commands.fs.StatFile", } def getFactory(command): diff --git a/slave/buildslave/test/unit/test_commands_fs.py b/slave/buildslave/test/unit/test_commands_fs.py index 775e1a1bdfc..b8ddd1887c6 100644 --- a/slave/buildslave/test/unit/test_commands_fs.py +++ b/slave/buildslave/test/unit/test_commands_fs.py @@ -111,3 +111,56 @@ def check(_): self.assertEqual(self.get_updates(), [{'rc': 1}], self.builder.show()) d.addErrback(check) return d + +class TestStatFile(CommandTestMixin, unittest.TestCase): + + def setUp(self): + self.setUpCommand() + + def tearDown(self): + self.tearDownCommand() + + def test_non_existant(self): + self.make_command(fs.StatFile, dict( + file='no-such-file', + ), True) + d = self.run_command() + + def check(_): + self.assertEqual(self.get_updates(), + [{'rc': 1}], + self.builder.show()) + d.addCallback(check) + return d + + def test_directory(self): + self.make_command(fs.StatFile, dict( + file='workdir', + ), True) + d = self.run_command() + + def check(_): + import stat + self.assertTrue(stat.S_ISDIR(self.get_updates()[0]['stat'][stat.ST_MODE])) + self.assertIn({'rc': 0}, + self.get_updates(), + self.builder.show()) + d.addCallback(check) + return d + + def test_file(self): + self.make_command(fs.StatFile, dict( + file='test-file', + ), True) + open(os.path.join(self.basedir, 'test-file'), "w") + + d = self.run_command() + + def check(_): + import stat + self.assertTrue(stat.S_ISREG(self.get_updates()[0]['stat'][stat.ST_MODE])) + self.assertIn({'rc': 0}, + self.get_updates(), + self.builder.show()) + d.addCallback(check) + return d