sapling/py_tar_utils/__init__.py
Siddharth Agarwal 2525c1ed46 move tar_utils.py from update_rust into an open sourceable location
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
2017-09-14 13:52:23 -07:00

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]