Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement b2 file unhide command #297

Merged
merged 17 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions b2/_internal/b2v3/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ class UploadFile(HyphenFilenameMixin, UploadFile):
B2.register_subcommand(GetDownloadAuth)
B2.register_subcommand(GetDownloadUrlWithAuth)
B2.register_subcommand(HideFile)
B2.register_subcommand(UnhideFile)
B2.register_subcommand(ListBuckets)
B2.register_subcommand(ListKeys)
B2.register_subcommand(ListParts)
Expand Down
1 change: 1 addition & 0 deletions b2/_internal/b2v4/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
B2.register_subcommand(GetDownloadAuth)
B2.register_subcommand(GetDownloadUrlWithAuth)
B2.register_subcommand(HideFile)
B2.register_subcommand(UnhideFile)
B2.register_subcommand(ListBuckets)
B2.register_subcommand(ListKeys)
B2.register_subcommand(ListParts)
Expand Down
59 changes: 59 additions & 0 deletions b2/_internal/console_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -2174,6 +2174,54 @@ def _run(self, args):
return 0


class FileUnhideBase(Command):
"""
Delete the "hide marker" for a given file.

Requires capability:

- **listFiles**
- **deleteFiles**

and optionally:

- **bypassGovernance**
"""

@classmethod
def _setup_parser(cls, parser):
add_bucket_name_argument(parser)
parser.add_argument('fileName').completer = file_name_completer

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like there was oversight on our part an we did not update b2 file hide to use B2URI when doing b2v4

Please correct our mistake, i.e.:

  • in this command only support b2uri argument
  • in b2 file hide support both new and old syntax, but the --help should be only speaking of new syntax
  • the b2v3 hide-file should remain unchanged

add_normalized_argument(parser, '--bypass-governance', action='store_true', default=False)
super()._setup_parser(parser)

def _run(self, args):
bucket = self.api.get_bucket_by_name(args.bucketName)
# get the latest file version
file_versions = bucket.list_file_versions(file_name=args.fileName, fetch_count=1)
latest_file_version = next(file_versions, None)
if latest_file_version is None:
self._print_stderr(f'ERROR: File not present: "{args.fileName}"')
return 1

action = latest_file_version.action
if action == "upload":
self._print_stderr(f'ERROR: File not currently hidden: "{args.fileName}"')
return 1
elif action == "delete":
self._print_stderr(f'ERROR: File deleted: "{args.fileName}"')
return 1
elif action != "hide":
self._print_stderr(f'ERROR: Unknown file version action: {action}')
return 1

file_id_and_name = bucket.delete_file_version(
latest_file_version.id_, args.fileName, args.bypass_governance
)
self._print_json(file_id_and_name)
mjurbanski-reef marked this conversation as resolved.
Show resolved Hide resolved
return 0


class BucketListBase(Command):
"""
List all of the buckets in the current account.
Expand Down Expand Up @@ -5078,6 +5126,12 @@ class FileHide(FileHideBase):
COMMAND_NAME = 'hide'


@File.subcommands_registry.register
class FileUnhide(FileUnhideBase):
__doc__ = FileUnhideBase.__doc__
COMMAND_NAME = 'unhide'


@File.subcommands_registry.register
class FileUpdate(FileUpdateBase):
__doc__ = FileUpdateBase.__doc__
Expand Down Expand Up @@ -5150,6 +5204,11 @@ class HideFile(CmdReplacedByMixin, FileHideBase):
replaced_by_cmd = (File, FileHide)


class UnhideFile(CmdReplacedByMixin, FileUnhideBase):
__doc__ = FileUnhideBase.__doc__
replaced_by_cmd = (File, FileUnhide)
mjurbanski-reef marked this conversation as resolved.
Show resolved Hide resolved


class UpdateFileLegalHold(CmdReplacedByMixin, UpdateFileLegalHoldBase):
__doc__ = UpdateFileLegalHoldBase.__doc__
replaced_by_cmd = (File, FileUpdate)
Expand Down
14 changes: 14 additions & 0 deletions test/integration/test_b2_command_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,20 @@ def test_basic(b2_tool, bucket_name, sample_file, tmp_path, b2_uri_args, apiver_
)
should_equal(['a', 'b/1', 'b/2', 'd'], [f['fileName'] for f in list_of_files])

b2_tool.should_succeed(['file', 'unhide', bucket_name, 'c'])

list_of_files = b2_tool.should_succeed_json(
['ls', '--json', '--recursive', *b2_uri_args(bucket_name)]
)
should_equal(['a', 'b/1', 'b/2', 'c', 'd'], [f['fileName'] for f in list_of_files])

b2_tool.should_succeed(['file', 'hide', bucket_name, 'c'])

list_of_files = b2_tool.should_succeed_json(
['ls', '--json', '--recursive', *b2_uri_args(bucket_name)]
)
should_equal(['a', 'b/1', 'b/2', 'd'], [f['fileName'] for f in list_of_files])

list_of_files = b2_tool.should_succeed_json(
['ls', '--json', '--recursive', '--versions', *b2_uri_args(bucket_name)]
)
Expand Down
11 changes: 9 additions & 2 deletions test/unit/test_console_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -2082,6 +2082,9 @@ def test_get_bucket_with_hidden(self):
console_tool.run_command(['b2', 'file', 'hide', 'my-bucket', 'hidden3'])
console_tool.run_command(['b2', 'hide-file', 'my-bucket', 'hidden4'])

# unhide one file
console_tool.run_command(['b2', 'file', 'unhide', 'my-bucket', 'hidden2'])

# Now check the output of `bucket get` against the canon.
expected_json = {
"accountId": self.account_id,
Expand All @@ -2093,7 +2096,7 @@ def test_get_bucket_with_hidden(self):
"defaultServerSideEncryption": {
"mode": "none"
},
"fileCount": 10,
"fileCount": 9,
"lifecycleRules": [],
"options": [],
"revision": 1,
Expand Down Expand Up @@ -2146,6 +2149,10 @@ def test_get_bucket_complex(self):
console_tool.run_command(['b2', 'file', 'hide', 'my-bucket', '1/2/hidden3'])
console_tool.run_command(['b2', 'file', 'hide', 'my-bucket', '1/2/hidden3'])

# Unhide a file
console_tool.run_command(['b2', 'file', 'unhide', 'my-bucket', '1/hidden2'])
console_tool.run_command(['b2', 'file', 'unhide', 'my-bucket', '1/hidden2'])

# Now check the output of `bucket get` against the canon.
expected_json = {
"accountId": self.account_id,
Expand All @@ -2157,7 +2164,7 @@ def test_get_bucket_complex(self):
"defaultServerSideEncryption": {
"mode": "none"
},
"fileCount": 29,
"fileCount": 28,
"lifecycleRules": [],
"options": [],
"revision": 1,
Expand Down
Loading