mirror of
https://github.com/facebook/sapling.git
synced 2024-10-16 11:52:02 +03:00
2525c1ed46
Summary: This is going to be useful for a small regenerate script I want to write and open source. Reviewed By: yfeldblum Differential Revision: D5831942 fbshipit-source-id: c1610ba1aa93061662e8cca3052f842b74fa4838
58 lines
1.6 KiB
Python
58 lines
1.6 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright (c) 2017-present, Facebook, Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
'''Utilities for dealing with tar files.'''
|
|
|
|
import os
|
|
import tarfile
|
|
|
|
from typing import List
|
|
|
|
|
|
def from_dirs(dirs: List[str], tar_filename: str):
|
|
'''Create a .tar.gz file from a given list of directories.'''
|
|
with tarfile.open(tar_filename, 'w:gz') as tar:
|
|
for dir in dirs:
|
|
tar.add(dir, arcname=os.path.basename(dir))
|
|
|
|
|
|
def extractall_safe(path: str, dest: str) -> str:
|
|
'''Extract a tar safely. Raise an exception if there are any bad paths.
|
|
|
|
Returns the subdirectory the files were extracted to.'''
|
|
tar = tarfile.open(path)
|
|
firstdir = _check_members(path, tar)
|
|
tar.extractall(dest)
|
|
return os.path.join(dest, firstdir)
|
|
|
|
|
|
def _check_members(path: str, tar: tarfile.TarFile) -> str:
|
|
firstdir = None
|
|
for finfo in tar:
|
|
if _badpath(finfo.name):
|
|
raise RuntimeError('{} has bad path: {}'.format(path, finfo.name))
|
|
if firstdir is None:
|
|
firstdir = _firstdir(finfo.name)
|
|
elif firstdir != _firstdir(finfo.name):
|
|
raise RuntimeError(
|
|
'{}: expected path {} to begin with {}'.
|
|
format(path, finfo.name, firstdir)
|
|
)
|
|
|
|
if firstdir is None:
|
|
raise RuntimeError('{}: empty tar file'.format(path))
|
|
|
|
return firstdir
|
|
|
|
|
|
def _badpath(path: str) -> bool:
|
|
return path.startswith('..') or path.startswith('/')
|
|
|
|
|
|
def _firstdir(rel_path: str) -> str:
|
|
return rel_path.split('/', 1)[0]
|