mirror of
https://github.com/deadc0de6/dotdrop.git
synced 2026-02-06 20:05:39 +00:00
add chmod to import command
This commit is contained in:
@@ -149,27 +149,28 @@ class CfgAggregator:
|
||||
"""remove this dotfile from this profile"""
|
||||
return self.cfgyaml.del_dotfile_from_profile(dotfile.key, profile.key)
|
||||
|
||||
def _create_new_dotfile(self, src, dst, link):
|
||||
def _create_new_dotfile(self, src, dst, link, chmod=None):
|
||||
"""create a new dotfile"""
|
||||
# get a new dotfile with a unique key
|
||||
key = self._get_new_dotfile_key(dst)
|
||||
if self.debug:
|
||||
self.log.dbg('new dotfile key: {}'.format(key))
|
||||
# add the dotfile
|
||||
self.cfgyaml.add_dotfile(key, src, dst, link)
|
||||
self.cfgyaml.add_dotfile(key, src, dst, link, chmod=chmod)
|
||||
return Dotfile(key, dst, src)
|
||||
|
||||
def new(self, src, dst, link):
|
||||
def new(self, src, dst, link, chmod=None):
|
||||
"""
|
||||
import a new dotfile
|
||||
@src: path in dotpath
|
||||
@dst: path in FS
|
||||
@link: LinkType
|
||||
@chmod: file permission
|
||||
"""
|
||||
dst = self.path_to_dotfile_dst(dst)
|
||||
dotfile = self.get_dotfile_by_src_dst(src, dst)
|
||||
if not dotfile:
|
||||
dotfile = self._create_new_dotfile(src, dst, link)
|
||||
dotfile = self._create_new_dotfile(src, dst, link, chmod=chmod)
|
||||
|
||||
key = dotfile.key
|
||||
ret = self.cfgyaml.add_dotfile_to_profile(key, self.profile_key)
|
||||
|
||||
@@ -58,6 +58,7 @@ class CfgYaml:
|
||||
key_dotfile_actions = 'actions'
|
||||
key_dotfile_noempty = 'ignoreempty'
|
||||
key_dotfile_template = 'template'
|
||||
key_dotfile_chmod = 'chmod'
|
||||
|
||||
# profile
|
||||
key_profile_dotfiles = 'dotfiles'
|
||||
@@ -316,7 +317,7 @@ class CfgYaml:
|
||||
"""return all existing dotfile keys"""
|
||||
return self.dotfiles.keys()
|
||||
|
||||
def add_dotfile(self, key, src, dst, link):
|
||||
def add_dotfile(self, key, src, dst, link, chmod=None):
|
||||
"""add a new dotfile"""
|
||||
if key in self.dotfiles.keys():
|
||||
return False
|
||||
@@ -324,14 +325,23 @@ class CfgYaml:
|
||||
self._dbg('adding new dotfile: {}'.format(key))
|
||||
self._dbg('new dotfile src: {}'.format(src))
|
||||
self._dbg('new dotfile dst: {}'.format(dst))
|
||||
self._dbg('new dotfile link: {}'.format(link))
|
||||
if chmod:
|
||||
self._dbg('new dotfile chmod: {}'.format(chmod))
|
||||
|
||||
df_dict = {
|
||||
self.key_dotfile_src: src,
|
||||
self.key_dotfile_dst: dst,
|
||||
}
|
||||
# link
|
||||
dfl = self.settings[self.key_settings_link_dotfile_default]
|
||||
if str(link) != dfl:
|
||||
df_dict[self.key_dotfile_link] = str(link)
|
||||
# chmod
|
||||
if chmod:
|
||||
df_dict[self.key_dotfile_chmod] = format(chmod, 'o')
|
||||
|
||||
# add to global dict
|
||||
self._yaml_dict[self.key_dotfiles][key] = df_dict
|
||||
self._dirty = True
|
||||
|
||||
@@ -623,6 +633,25 @@ class CfgYaml:
|
||||
if self.key_dotfile_template not in v:
|
||||
val = self.settings.get(self.key_settings_template, True)
|
||||
v[self.key_dotfile_template] = val
|
||||
# validate value of chmod if defined
|
||||
if self.key_dotfile_chmod in v:
|
||||
val = v[self.key_dotfile_chmod]
|
||||
if len(val) < 3:
|
||||
err = 'bad format for chmod: {}'.format(val)
|
||||
self._log.err(err)
|
||||
raise YamlException('dotfile chmod error: {}'.format(err))
|
||||
try:
|
||||
int(val)
|
||||
except Exception:
|
||||
err = 'bad format for chmod: {}'.format(val)
|
||||
self._log.err(err)
|
||||
raise YamlException('dotfile chmod error: {}'.format(err))
|
||||
for x in val:
|
||||
y = int(x)
|
||||
if y < 0 or y > 7:
|
||||
err = 'bad format for chmod: {}'.format(val)
|
||||
self._log.err(err)
|
||||
raise YamlException('dotfile chmod error: {}'.format(err))
|
||||
|
||||
return new
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ from dotdrop.installer import Installer
|
||||
from dotdrop.updater import Updater
|
||||
from dotdrop.comparator import Comparator
|
||||
from dotdrop.utils import get_tmpdir, removepath, strip_home, \
|
||||
uniq_list, patch_ignores, dependencies_met
|
||||
uniq_list, patch_ignores, dependencies_met, get_file_perm
|
||||
from dotdrop.linktypes import LinkTypes
|
||||
from dotdrop.exceptions import YamlException, UndefinedException
|
||||
|
||||
@@ -426,6 +426,9 @@ def cmd_importer(o):
|
||||
strip = os.sep
|
||||
src = src.lstrip(strip)
|
||||
|
||||
# get the permission
|
||||
perm = get_file_perm(dst)
|
||||
|
||||
# set the link attribute
|
||||
linktype = o.import_link
|
||||
if linktype == LinkTypes.LINK_CHILDREN and \
|
||||
@@ -485,16 +488,23 @@ def cmd_importer(o):
|
||||
LOG.err('importing \"{}\" failed!'.format(path))
|
||||
ret = False
|
||||
continue
|
||||
|
||||
if o.dry:
|
||||
LOG.dry('would copy {} to {}'.format(dst, srcf))
|
||||
else:
|
||||
# copy the file to the dotpath
|
||||
if os.path.isdir(dst):
|
||||
if os.path.exists(srcf):
|
||||
shutil.rmtree(srcf)
|
||||
shutil.copytree(dst, srcf)
|
||||
else:
|
||||
shutil.copy2(dst, srcf)
|
||||
retconf = o.conf.new(src, dst, linktype)
|
||||
|
||||
chmod = None
|
||||
if o.import_mode or perm&o.umask:
|
||||
# insert chmod
|
||||
chmod = perm
|
||||
retconf = o.conf.new(src, dst, linktype, chmod=chmod)
|
||||
if retconf:
|
||||
LOG.sub('\"{}\" imported'.format(path))
|
||||
cnt += 1
|
||||
|
||||
@@ -22,7 +22,7 @@ class Dotfile(DictParser):
|
||||
actions=[], trans_r=None, trans_w=None,
|
||||
link=LinkTypes.NOLINK, noempty=False,
|
||||
cmpignore=[], upignore=[],
|
||||
instignore=[], template=True):
|
||||
instignore=[], template=True, chmod=None):
|
||||
"""
|
||||
constructor
|
||||
@key: dotfile key
|
||||
@@ -37,6 +37,7 @@ class Dotfile(DictParser):
|
||||
@cmpignore: patterns to ignore when comparing
|
||||
@instignore: patterns to ignore when installing
|
||||
@template: template this dotfile
|
||||
@chmod: file permission
|
||||
"""
|
||||
self.actions = actions
|
||||
self.dst = dst
|
||||
@@ -50,6 +51,7 @@ class Dotfile(DictParser):
|
||||
self.cmpignore = cmpignore
|
||||
self.instignore = instignore
|
||||
self.template = template
|
||||
self.chmod = chmod
|
||||
|
||||
if self.link != LinkTypes.NOLINK and \
|
||||
(
|
||||
@@ -113,6 +115,7 @@ class Dotfile(DictParser):
|
||||
msg += ', dst:\"{}\"'.format(self.dst)
|
||||
msg += ', link:\"{}\"'.format(str(self.link))
|
||||
msg += ', template:{}'.format(self.template)
|
||||
msg += ', chmod:{}'.format(self.chmod)
|
||||
return msg
|
||||
|
||||
def prt(self):
|
||||
@@ -123,6 +126,7 @@ class Dotfile(DictParser):
|
||||
out += '\n{}dst: \"{}\"'.format(indent, self.dst)
|
||||
out += '\n{}link: \"{}\"'.format(indent, str(self.link))
|
||||
out += '\n{}template: \"{}\"'.format(indent, str(self.template))
|
||||
out += '\n{}chmod: \"{}\"'.format(indent, str(self.chmod))
|
||||
|
||||
out += '\n{}pre-action:'.format(indent)
|
||||
some = self.get_pre_actions()
|
||||
|
||||
@@ -16,7 +16,7 @@ from dotdrop.linktypes import LinkTypes
|
||||
from dotdrop.logger import Logger
|
||||
from dotdrop.cfg_aggregator import CfgAggregator as Cfg
|
||||
from dotdrop.action import Action
|
||||
from dotdrop.utils import uniq_list
|
||||
from dotdrop.utils import uniq_list, get_umask
|
||||
from dotdrop.exceptions import YamlException
|
||||
|
||||
ENV_PROFILE = 'DOTDROP_PROFILE'
|
||||
@@ -54,7 +54,7 @@ USAGE = """
|
||||
Usage:
|
||||
dotdrop install [-VbtfndDa] [-c <path>] [-p <profile>]
|
||||
[-w <nb>] [<key>...]
|
||||
dotdrop import [-Vbdf] [-c <path>] [-p <profile>] [-s <path>]
|
||||
dotdrop import [-Vbdfm] [-c <path>] [-p <profile>] [-s <path>]
|
||||
[-l <link>] <path>...
|
||||
dotdrop compare [-LVb] [-c <path>] [-p <profile>]
|
||||
[-C <file>...] [-i <pattern>...]
|
||||
@@ -73,15 +73,16 @@ Options:
|
||||
-c --cfg=<path> Path to the config.
|
||||
-C --file=<path> Path of dotfile to compare.
|
||||
-d --dry Dry run.
|
||||
-l --link=<link> Link option (nolink|link|link_children).
|
||||
-L --file-only Do not show diff but only the files that differ.
|
||||
-p --profile=<profile> Specify the profile to use [default: {}].
|
||||
-D --showdiff Show a diff before overwriting.
|
||||
-f --force Do not ask user confirmation for anything.
|
||||
-G --grepable Grepable output.
|
||||
-i --ignore=<pattern> Pattern to ignore.
|
||||
-k --key Treat <path> as a dotfile key.
|
||||
-l --link=<link> Link option (nolink|link|link_children).
|
||||
-L --file-only Do not show diff but only the files that differ.
|
||||
-m --preserve-mode Insert a chmod entry in the dotfile with its permissions.
|
||||
-n --nodiff Do not diff when installing.
|
||||
-p --profile=<profile> Specify the profile to use [default: {}].
|
||||
-P --show-patch Provide a one-liner to manually patch template.
|
||||
-s --as=<path> Import as a different path from actual path.
|
||||
-t --temp Install to a temporary directory for review.
|
||||
@@ -121,6 +122,7 @@ class Options(AttrMonitor):
|
||||
self.log = Logger()
|
||||
self.debug = self.args['--verbose'] or ENV_DEBUG in os.environ
|
||||
self.dry = self.args['--dry']
|
||||
self.umask = get_umask()
|
||||
if ENV_NODEBUG in os.environ:
|
||||
# force disabling debugs
|
||||
self.debug = False
|
||||
@@ -261,6 +263,7 @@ class Options(AttrMonitor):
|
||||
# "import" specifics
|
||||
self.import_path = self.args['<path>']
|
||||
self.import_as = self.args['--as']
|
||||
self.import_mode = self.args['--preserve-mode']
|
||||
|
||||
# "update" specifics
|
||||
self.update_path = self.args['<path>']
|
||||
|
||||
@@ -302,3 +302,15 @@ def mirror_file_rights(src, dst):
|
||||
"""mirror file rights of src to dst (can rise exc)"""
|
||||
rights = os.stat(src).st_mode
|
||||
os.chmod(dst, rights)
|
||||
|
||||
|
||||
def get_umask():
|
||||
"""return current umask value"""
|
||||
cur = os.umask(0)
|
||||
os.umask(cur)
|
||||
return 0o777-cur
|
||||
|
||||
|
||||
def get_file_perm(path):
|
||||
"""return file permission"""
|
||||
return os.stat(path).st_mode & 0o777
|
||||
|
||||
Reference in New Issue
Block a user