Valentin David pushed to branch valentindavid/pull-chmod-bug at BuildStream / buildstream
Commits:
- 
5f50d3bd
by Valentin David at 2019-02-12T10:31:01Z
2 changed files:
Changes:
| ... | ... | @@ -374,9 +374,7 @@ class CASCache(): | 
| 374 | 374 |                      for chunk in iter(lambda: tmp.read(4096), b""):
 | 
| 375 | 375 |                          h.update(chunk)
 | 
| 376 | 376 |                  else:
 | 
| 377 | -                    tmp = stack.enter_context(utils._tempnamedfile(dir=self.tmpdir))
 | |
| 378 | -                    # Set mode bits to 0644
 | |
| 379 | -                    os.chmod(tmp.name, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
 | |
| 377 | +                    tmp = stack.enter_context(self._temporary_object())
 | |
| 380 | 378 |  | 
| 381 | 379 |                      if path:
 | 
| 382 | 380 |                          with open(path, 'rb') as f:
 | 
| ... | ... | @@ -825,6 +823,19 @@ class CASCache(): | 
| 825 | 823 |          for dirnode in directory.directories:
 | 
| 826 | 824 |              yield from self._required_blobs(dirnode.digest)
 | 
| 827 | 825 |  | 
| 826 | +    # _temporary_object():
 | |
| 827 | +    #
 | |
| 828 | +    # Returns:
 | |
| 829 | +    #     (file): A file object to a named temporary file.
 | |
| 830 | +    #
 | |
| 831 | +    # Create a named temporary file with 0o0644 access rights.
 | |
| 832 | +    @contextlib.contextmanager
 | |
| 833 | +    def _temporary_object(self):
 | |
| 834 | +        with utils._tempnamedfile(dir=self.tmpdir) as f:
 | |
| 835 | +            os.chmod(f.name,
 | |
| 836 | +                     stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
 | |
| 837 | +            yield f
 | |
| 838 | + | |
| 828 | 839 |      # _ensure_blob():
 | 
| 829 | 840 |      #
 | 
| 830 | 841 |      # Fetch and add blob if it's not already local.
 | 
| ... | ... | @@ -842,7 +853,7 @@ class CASCache(): | 
| 842 | 853 |              # already in local repository
 | 
| 843 | 854 |              return objpath
 | 
| 844 | 855 |  | 
| 845 | -        with utils._tempnamedfile(dir=self.tmpdir) as f:
 | |
| 856 | +        with self._temporary_object() as f:
 | |
| 846 | 857 |              remote._fetch_blob(digest, f)
 | 
| 847 | 858 |  | 
| 848 | 859 |              added_digest = self.add_object(path=f.name, link_directly=True)
 | 
| ... | ... | @@ -852,7 +863,7 @@ class CASCache(): | 
| 852 | 863 |  | 
| 853 | 864 |      def _batch_download_complete(self, batch):
 | 
| 854 | 865 |          for digest, data in batch.send():
 | 
| 855 | -            with utils._tempnamedfile(dir=self.tmpdir) as f:
 | |
| 866 | +            with self._temporary_object() as f:
 | |
| 856 | 867 |                  f.write(data)
 | 
| 857 | 868 |                  f.flush()
 | 
| 858 | 869 |  | 
| 1 | 1 |  import os
 | 
| 2 | 2 |  import shutil
 | 
| 3 | +import stat
 | |
| 3 | 4 |  import pytest
 | 
| 4 | 5 |  from buildstream.plugintestutils import cli
 | 
| 5 | 6 |  from tests.testutils import create_artifact_share, generate_junction
 | 
| ... | ... | @@ -462,3 +463,74 @@ def test_build_remote_option(caplog, cli, tmpdir, datafiles): | 
| 462 | 463 |          assert shareproject.repo not in result.stderr
 | 
| 463 | 464 |          assert shareuser.repo not in result.stderr
 | 
| 464 | 465 |          assert sharecli.repo in result.stderr
 | 
| 466 | + | |
| 467 | + | |
| 468 | +@pytest.mark.datafiles(DATA_DIR)
 | |
| 469 | +def test_pull_access_rights(caplog, cli, tmpdir, datafiles):
 | |
| 470 | +    project = str(datafiles)
 | |
| 471 | +    checkout = os.path.join(str(tmpdir), 'checkout')
 | |
| 472 | + | |
| 473 | +    # Work-around datafiles not preserving mode
 | |
| 474 | +    os.chmod(os.path.join(project, 'files/bin-files/usr/bin/hello'), 0o0755)
 | |
| 475 | + | |
| 476 | +    # We need a big file that does not go into a batch to test a different
 | |
| 477 | +    # code path
 | |
| 478 | +    os.makedirs(os.path.join(project, 'files/dev-files/usr/share'), exist_ok=True)
 | |
| 479 | +    with open(os.path.join(project, 'files/dev-files/usr/share/big-file'), 'w') as f:
 | |
| 480 | +        buf = ' ' * 4096
 | |
| 481 | +        for _ in range(1024):
 | |
| 482 | +            f.write(buf)
 | |
| 483 | + | |
| 484 | +    with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare')) as share:
 | |
| 485 | + | |
| 486 | +        cli.configure({
 | |
| 487 | +            'artifacts': {'url': share.repo, 'push': True}
 | |
| 488 | +        })
 | |
| 489 | +        result = cli.run(project=project, args=['build', 'compose-all.bst'])
 | |
| 490 | +        result.assert_success()
 | |
| 491 | + | |
| 492 | +        result = cli.run(project=project,
 | |
| 493 | +                         args=['artifact', 'checkout',
 | |
| 494 | +                               '--hardlinks', '--no-integrate',
 | |
| 495 | +                               'compose-all.bst',
 | |
| 496 | +                               '--directory', checkout])
 | |
| 497 | +        result.assert_success()
 | |
| 498 | + | |
| 499 | +        st = os.lstat(os.path.join(checkout, 'usr/include/pony.h'))
 | |
| 500 | +        assert stat.S_ISREG(st.st_mode)
 | |
| 501 | +        assert stat.S_IMODE(st.st_mode) == 0o0644
 | |
| 502 | + | |
| 503 | +        st = os.lstat(os.path.join(checkout, 'usr/bin/hello'))
 | |
| 504 | +        assert stat.S_ISREG(st.st_mode)
 | |
| 505 | +        assert stat.S_IMODE(st.st_mode) == 0o0755
 | |
| 506 | + | |
| 507 | +        st = os.lstat(os.path.join(checkout, 'usr/share/big-file'))
 | |
| 508 | +        assert stat.S_ISREG(st.st_mode)
 | |
| 509 | +        assert stat.S_IMODE(st.st_mode) == 0o0644
 | |
| 510 | + | |
| 511 | +        shutil.rmtree(checkout)
 | |
| 512 | + | |
| 513 | +        artifacts = os.path.join(cli.directory, 'artifacts')
 | |
| 514 | +        shutil.rmtree(artifacts)
 | |
| 515 | + | |
| 516 | +        result = cli.run(project=project, args=['artifact', 'pull', 'compose-all.bst'])
 | |
| 517 | +        result.assert_success()
 | |
| 518 | + | |
| 519 | +        result = cli.run(project=project,
 | |
| 520 | +                         args=['artifact', 'checkout',
 | |
| 521 | +                               '--hardlinks', '--no-integrate',
 | |
| 522 | +                               'compose-all.bst',
 | |
| 523 | +                               '--directory', checkout])
 | |
| 524 | +        result.assert_success()
 | |
| 525 | + | |
| 526 | +        st = os.lstat(os.path.join(checkout, 'usr/include/pony.h'))
 | |
| 527 | +        assert stat.S_ISREG(st.st_mode)
 | |
| 528 | +        assert stat.S_IMODE(st.st_mode) == 0o0644
 | |
| 529 | + | |
| 530 | +        st = os.lstat(os.path.join(checkout, 'usr/bin/hello'))
 | |
| 531 | +        assert stat.S_ISREG(st.st_mode)
 | |
| 532 | +        assert stat.S_IMODE(st.st_mode) == 0o0755
 | |
| 533 | + | |
| 534 | +        st = os.lstat(os.path.join(checkout, 'usr/share/big-file'))
 | |
| 535 | +        assert stat.S_ISREG(st.st_mode)
 | |
| 536 | +        assert stat.S_IMODE(st.st_mode) == 0o0644 | 
