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