https://www.atlassian.com/fr/git/tutorials
https://git-scm.com/docs
TOC
| chapter | ||
|---|---|---|
| REFERENCE | - ADD | - MERGE |
| USED | - ARCHIVE | - PULL |
| URL | - BRANCH | - PUSH |
| VALUES | - CHECKOUT | - REMOTE |
| GPG | - CLONE | - REBASE |
| GITIGNORE | - COMMIT | - RESET |
| TRICKS | - FETCH | - STASH |
| CONFIG | - LOG | - SUBMODULE |
| - LOG | - SWITCH | |
| - LOG | - TAG |
USEFULL OPTIONS
git -C <path> <commands> # launch git commands in <path> repo
REFERENCE
URL
https://<fqdn>/<user>/<project> # https://github.com/aguytech/Shaarli
git@<fqdn>:<user>/<project>.git # git@github.com:aguytech/Shaarli.git
VALUES
git rev-parse --symbolic-full-name --abbrev-ref @{upstream} # print value for upstream
git rev-parse --symbolic-full-name --abbrev-ref @{push} # print value for push
git for-each-ref --format='%(refname:short) <- %(upstream:short)' refs/heads # show all upstream
git for-each-ref --format='%(upstream:short)' "$(git symbolic-ref -q HEAD)" # idem
git for-each-ref --format='%(refname:short) <- %(push:short)' refs/heads # show all upstream
git for-each-ref --format='%(push:short)' "$(git symbolic-ref -q HEAD)" # idem
USED
ADD
git add -i / --interactive # add with interactively mode
git add -u / --update # Update the index for already referred files (just where it already has an entry matching <pathspec>
gi add -A / --all / --no-ignore-removal # add all files
ARCHIVE
git archive -l # list available formats
git archive --format tar.gz -9 -o "$(git br --show-current).$(date +%s).tar.gz" <branch> # create an archive from local <branch> with best compression -9 & in format tar.gz
BRANCH
https://stackoverflow.com/questions/11266478/git-add-remote-branch
list
git branch / git br # print list of local branches
git br -v # print informations about local branches
git br -vv # print full information about local branches
git branch -a -vv # print full information about all branches
git br --show-current # show name of current branch
git br -r # print list of remote branches for all repositories
git br -rlv <remote>/<pattern> # list remote branches for <remote> repository & with name matched <pattern>
create
git br <branch> # create a local branch
git br <branch> <remote>/<remote_branch> # create local branch from remote
git push <upstream> <branch> # create remote branch from existing local one
delete
git br -d <branch> # delete local branch
git br -rd <remote>/<branch> # delete remote branch
rename
# local
git br -m <old-branch> <new-branch># rename local branch
# remote
git br -m <old-branch> <new-branch># rename local branch
git push origin --delete <old-branch>
git push origin <new-branch>
attach to upstream
git fetch # retrieves upsteram branches if already exists
git br -u <upstream>/<remote_branch> <branch> # attach a local branch to remote existing one
git br --set-upstream-to=<upstream>/<remote_branch> <branch>
CHECKOUT
git co -b <branch> # create a branch from HEAD and switch to it
git co -t <repo>/<branch> -b <branch> # create a local branch from <repo>/<branch> and set upstream
git co --orphan=<branch> # create an orphan branch (whithout history)
git co --orphan=<branch> # create an orphan branch (whithout history)
git co --detach -b <branch> # check out a commit for inspection and discardable experiments
CLONE
git clone <url> # clone a repository
git clone <url> <path> # clone a repository and change path name to <path>
git clone -b <branch> <url> # clone only one branch from repository
git clone -b v0.11-snippets --single-branch --no-tags git@github.com:aguytech/Shaarli.git shaarli-snippets # clone from a repository a single branch
COMMIT
# amend
git commit --amend --no-edit # amends a commit without changing its commit message
git commit --amend -m "message" # amends a commit with a new message
DIFF
git diff <file> # view the changes you made relative to the index (staging area for the next commit)
git diff HEAD README.md <file> # view the changes between index and HEAD
git diff @{u} # view the changes between local and upstream branch
FETCH
git fetch upstream : Get informations from upstream for all branches
git fetch upstream <branch> : Get informations from upstream only for the branch
CONFIG
# amend
git config --global init.defaultBranch main # set main as the default branch
git config <variable> # show variable and his value
git config --global core.editor vim # set selected editor
git config -l # list all config variables
git config -l --show-origin # list all config variables with their origins
git config -l --name-only # list all names of system config variables
git config -l --local # list all config variables defined for user
git config -l --global # list all global config variables for global users
git config -l --system # list all system config variables for system
LOG
git log # show logs
git log HEAD~2 <repo>/<branch> # show after the last 2nd commits
git log -3 <repo>/<branch> # show only last 3 lines of logs
git log --pretty=format:'%h' -n1 <repo>/<branch> # show short sha of last commit
git log --name-only # with file names
git log --name-status # with file names with its status
git log --stat # with file names with its statisticals
git reflog # show logs with a reference (sha) view
MERGE
git merge -m "message" <branch> # merge branch with actual one with a message to committing
git merge --allow-unrelated-histories <branch> # allows to merge branch with no common history
PULL
If you tried a pull which resulted in complex conflicts and would want to start over, you can recover with git reset
git pull # Update actual local branch from current remote
git pull <remote> # Update actual local branch from a selected remote
git pull <remote> <branch> # Merge into the current branch the remote branch
<=>
git fetch origin
git merge origin/next
git pull --rebase # pull automatically last modifications on remote (with fetch + merge) & put your validation on head directly
pull all submodules
git submodule foreach git pull
git submodule foreach git pull origin main
git submodule foreach 'git pull origin main || true' # for some submodules without updates"
PUSH
-q, --quiet Suppress all output
-v, --verbose show details
--progress show progress status
git push --all | --branches # push all branches
git push --tags # push all tags
git push -u <upstream> <branch> # Update remote refs along with associated objects
git push -u <upstream> <branch> # set upstream for actual local branch & push it to remote (create one if needed)
git push --tags # push tags also
git push -d <upstream> <branch> # delete remote branch
git push -d <upstream> <tag> # delete remote tag
REMOTE
git remote -v # show upstream
git remote add <name> <url> # add a remote source to repository
git remote add -t <branch> <name> <url> # add a remote source to repository only for the branch <branch>
git remote remove <name> # remove/delete the remote source <name>
git remote rename <name> <new_name> # rename a remote source
git remote set-branches <name> <branch1> <branch2> ... # change list of branches tracked by a remote
git remote set-url [--push] <name> <newurl> [<oldurl>] # manipulate push urls
git remote set-url [--add|--delete] <name> <url> # add or delete url
git remote show # list all upstreams
git remote show <name> # show details for a upstream
REBASE
In the same branch
git co <branch> # put HEAD on branch
git rebase --onto <newcommit> <oldcommit> <HEADcommit> # rebase to <newcommit> with attached HEAD
git push --force-with-lease github HEAD:<branch>
git reset --soft <newcommit> # reset branch to <newcommit>
git co <branch> # put HEAD on branch
After, informs others concerned developers to fetch and reset to the new HEAD
RESET
git reset --merge # resets the index and updates the files in the working tree that are different between <commit> and HEAD
git reset --hard <commit_sha> # reset branch to commit_sha, 'git reflog' is an better way to find commit_sha
git reset --hard HEAD~1
SWITCH
TAG
git tag # List all tags
git show-ref --tags # List all tags with references
git tag -a -m "message" <tag> # Defines an unsigned, annoted tag
git tag -s "tag" -m "message" <tag> # Creates a signed tag with message (define the default key with git config --global user.signingkey before)
git tag -s <tag> -u <keyid> -m <message> <tag> # Creates a signed tag with a specified key user
git tag -d <tag> # Delete existing tags with the given names
git tag -v <tag> # Verify the GPG signature of the given tag names
git show-ref --tags # show sha commits with associated tag
git push --delete origin <tag> # delete tag in origin
# rename tag
git tag -d <old>
git push origin -d <old> | git push origin :old
git tag <new>
git push origin <new> | git push origin --tags
git pull --prune --tags # for coworkers
SUBMODULE
add
git submodule add <url> <name> # Add submodule to actual repository in path <path>
git add .gitmodules <name> # Add new file and path to index
git commit -m "<name>: Add submodule <url> to /<name>" # Commit changes
update
git submodule update --init --recursive <pathspec> # initialize and clone submodules within based on the provided <pathspec>
remove
git rm --cached $pathsubmodule # delete main entry point in git
rm -rf .git/modules/$pathsubmodule # delete submodule from index
rm -rf $pathsubmodule # delete files of submodule
- In file <repo>/.gitmodules, remove section for the corresponding submodule
git add .gitmodules # add modifications in .gitmodules file to index
git commit -m "Remove submodule $pathsubmodule"
git push <upstream> <branch> # git push github main # push branch to origin
clone repo & submodules
git clone --no-remote-submodules <url> <path> # clone repo whithout associated submodules
git clone <url> <path>
git clone --remote-submodules <url> <path> # clone will use the status of the submodule’s remote-tracking branch. After use 'git submodule init' and 'git submodule update'
git clone --recurse-submodules <url> <path> # clone repository and its all submodules recursively
git clone --recurse-submodules[=<pathspec>] <url> <path> # clone repository and its filtered submodules by pathspec
STASH
git stash # Stash the changes in a dirty working directory away
git stash push -m "message" # Stash with a message
git stash list # List all stahes
git stash apply stash@{<index>} # Apply a sepcific stash
git stash pop # Apply the last stash and delete it
git stash drop stash@{<index>} # Drop a specific stash
git stash clear # Delete all stashes
git stash branch <branchname> stash@{<index>} # create a branch from a specific stash
GPG
https://kamarada.github.io/en/2019/07/14/using-git-with-ssh-keys/
GITIGNORE
https://www.atlassian.com/git/tutorials/saving-changes/gitignore
pattern
**/path # match directories anywhere in the repository, relative definition
*.pattern # matches zero or more characters
!pattern # mark to a pattern negates it
/pattern # matches files only in the repository root
path/ # appending a slash indicates the pattern is a directory
debug?.log # a question mark matches exactly one character
debug[0-9].log # Square brackets matches a single character from a specified range like [01] [a-z] [A-Z]
debug[!01].log # an exclamation mark matches any character except one from the specified set
logs/**/debug.log # a double asterisk matches zero or more directories like logs/*day/debug.log
example
*.ba[kt]
*~
!myfile.a # include file in repo
tmp/ # exclude all files in directory tmp
head/**/*.tmp # exclude all files *.tmp in subdirectory of head
TRICKS
StartupWMClass
alt+f2
lg
select windows
getattribute and setattr
'getattribute' and 'setattr' are two special methods (dunder methods) used to control access to a class's attributes. Here's a clear explanation of their role and differences:
getattribute(self, name)
Role: Called every time an attribute is accessed (read), even if the attribute doesn't exist
Default behavior: Searches for the attribute in the instance, then in the class, and then in the parent classes
usefulness
- Intercept access to an attribute to add logic (e.g., logging, validation)
- Raise an exception if the attribute is not allowed
Caution
If you override 'getattribute', you must call 'super().getattribute(name)' to avoid blocking access to internal attributes
setattr(self, name, value)
Role: Called whenever an attribute is modified (written)
Default behavior: Stores the value in the instance
usefulness
- Validate or modify the value before assigning it
- Prevent modification of certain attributes
- Synchronize attributes with other data
Caution
If you override 'setattr', you must use 'self.dict[name] = value' to avoid infinite recursion
example
class Temperature:
def __get__(self, obj, objtype):
print("desc __get__")
return obj._temperature
def __set__(self, obj, value):
print(f"desc __set__ {value}")
obj._temperature = value
class Maison:
def __init__(self, temperature):
self.temperature = temperature
def __getattribute__(self, attr):
print(f"__getattribute__ : {attr}")
return object.__getattribute__(self, attr)
def __setattr__(self, attr, value):
print(f"__setatt__ : {attr} - {value}")
return object.__setattr__(self, attr, value)
temperature = Temperature()
m = Maison(18)
__setatt__ : temperature - 18
desc __set__ 18
__setatt__ : _temperature - 18
m.temperature
__getattribute__ : temperature
desc __get__
__getattribute__ : _temperature
m.temperature = 22
__setatt__ : temperature - 22
desc __set__ 22
__setatt__ : _temperature - 22
m.x = 10
__setatt__ : x - 10
m.x
__getattribute__ : x
m.y
__getattribute__ : y
__getattribute__ : __dir__
__getattribute__ : __dict__
__getattribute__ : __class__
AttributeError: 'Maison' object has no attribute 'y'
getattr(self, name)
'getattr' is a special method (or dunder method) that is called when an attribute is not found in a class instance using the standard methods (getattribute, hasattr, etc.)
It allows you to dynamically manage access to missing attributes
usefulness
-
Creating attributes on the fly
-
Implementing default behaviors for undefined attributes
-
Proxies or wrappers: To redirect attribute calls to another object
-
Dynamic attributes: To generate values based on the attribute name
-
Compatibility with external APIs: To manage attributes that do not yet exist in a class
example
class Redirector:
def __init__(self, id):
self.id = id
def __repr__(self):
return f"Redirector2({self.id})"
def __getattr__(self, name):
def forwarder(arg):
return f"{self.id} -> {name}({arg})"
return forwarder
R = Redirector(2)
print(R)
print(R.bar(20))property
'@property' decorator allows you to define a method as a property of a class. This means you can access that method as if it were an attribute, without using parentheses to call a method.
- No parentheses: object.property (not object.property()).
- Convention: Use _<name> for the "private" attribute (e.g., _name).
- Validation: The setter can include checks.
- Compatibility: Works with inheritance and abstract classes.
example
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value <= 0:
raise ValueError("The radius must be positive")
self._radius = value
@radius.deleter
def radius(self):
print("Deleting the radius")
del self._radius
c = Circle(5)
print(c.radius)
>>> 5
c.radius = 10
del c.radius
descriptor
A Python descriptor is an object that implements at least one of the following special methods:
__get__(self, obj, objtype=None)
__set__(self, obj, value)
__delete__(self, obj)
These methods allow you to customize access to, modification of, or deletion of an attribute of a class instance
usefulness
- Data validation: Check or transform values before assigning them
- Dynamic calculations: Generate a value on the fly (e.g., @property properties)
- Data sharing: Manage common attributes between multiple instances
examples
class DescriptorTemperature:
TEMPMAX = 20
def __get__(self, obj, objtype=None):
print('__get__')
return obj._temperature
def __set__(self, obj, value):
print('__set__')
if value > __class__.TEMPMAX:
raise ValueError(f"Temperature is too hot:{value}, max:{__class__.TEMPMAX} ")
obj._temperature = value
class Home:
def __init__(self, temperature):
self.temperature = temperature
temperature = DescriptorTemperature()
h = Home(18)
print(h.temperature)
h.temperature = 20
h.temperature = 30metaclass
A metaclass is a class that defines the behavior of other classes. By default, in Python, classes are instances of 'type', which is the default metaclass. However, you can create your own metaclasses to control class creation, add attributes, or modify class behavior.
usefulness
- Control class creation: Add attributes, validate properties, or modify the class before it is finalized
- Singleton: Ensure that a class has only one instance
- Automatic validation: Verify that certain methods or attributes exist in the classes that use them
- Automatic registration: Register classes in a registry (for example, for a plugin system)
new
- Role: 'new' is responsible for memory allocation and instance creation
- Signature: new(cls, name, bases, namespace)
- Return: It must return a new instance of the class (or another class if necessary)
usefulness
- To create singletons (a single instance of a class)
- To modify the type of the returned instance (for example, to return a subclass)
- To control object creation (e.g., validation before creation)
class LowerAttrType(type):
def __new__(cls, name, bases, namespace, **kwds):
namespace = {(n.lower() if not n.startswith('__') else n): obj for n, obj in namespace.items()}
bases = (BaseOfAll,)
return type.__new__(cls, name, bases, namespace, **kwds)
class BaseOfAll:
def common_func(self):
return f"in common_func"
class C(metaclass=LowerAttrType):
def fUnc_bAd_CAP(selfself):
return f"in fUnc_bAd_CAP"
c = C()
print('func_bad_cap', 'func_bad_cap' in c.__dir__())
>>> True
print('fUnc_bAd_CAP', 'fUnc_bAd_CAP' in c.__dir__())
>>> False
print('c.common_func', c.common_func())
>>> c.common_func in common_func
print('c.func_bad_cap', c.func_bad_cap())
>>> c.func_bad_cap in fUnc_bAd_CAPIn Python, a closure is a function that captures local variables from its lexical environment, even when the function is called outside of that environment.
The closure retains a reference to the parent function's variables, not their values at any given time
If the parent variable is modified after the closure is created, the closure will see the new value
def add_n(n):
def f(x):
return x + n
return f
add_10 = add_n(10)
print(add_10(100))
>>> 110
print('closure len', add_10.__closure__.__len__())
>>> 1
print('closure content', add_10.__closure__[0].cell_contents)
>>> 10
usefulness
Decorators: Closures are often used to create decorators
Function factories: Create functions with predefined behaviors
Context memory: Preserve state between function calls
modified closure value
nonlocal
def counter_call(f):
counter = 0
def wrapper(*args, **kargs):
nonlocal counter # set counter is non local attribute but free variable
counter += 1
r = f(*args, **kargs)
print(f"{f.__name__} called {counter} times")
return r
return wrapper
@counter_call
def poly(n):
return sum(i**5 for i in range(n))
function attribute
def counter_call(f):
def wrapper(*args, **kargs):
wrapper.counter += 1
r = f(*args, **kargs)
print(f"{f.__name__}() called {wrapper.counter} times")
return r
wrapper.counter = 0 # evaluate before wrapper calling
return wrapper
@counter_call
def poly(n):
return sum(i**5 for i in range(n))
r = poly(10)
>>> poly() called 1 times
print(poly(10))
>>> poly() called 2 times
print(poly.counter) # poly = wrapper(poly) et wrapper has attribute counter
>>> 2try except
https://docs.python.org/3/tutorial/errors.html#handling-exceptions
syntax
try:
....
# Catch only Error_name
except Error_class as e:
...
except Error_class2 as e:
...
else
...
# Execute always instructions at the end even after a return
finally
Catch all errors
try:
...
except:
...
...
example
def return_with_finally(number):
try:
return 1/number
except ValueError as e:
print(f"e.args, {e.args}")
return("zero-divide")
except ZeroDivisionError as e:
print(f"OOPS, {type(e)}, {e}")
return("zero-divide")
except TypeError as e:
# interrupt treatment with the error
raise
finally:
print("always executed even after a return in 'except'")
raise
http://www.python.50webs.com/CHAP_8/chap_8.html
Best Practices
- Use specific exceptions rather than generic ones
- Provide clear error messages
- Avoid throwing exceptions for normal control flow cases (prefer explicit returns).
launch a specific Error Class with text
raise ErrorClass("personalized message")
main class errors
AssertionError # Assertion (assert) failed
AttributeError # Attribute or method not found for an object
FileNotFoundError # File not found during an input/output operation
ImportError # Module or function not found during an import
IndentationError # Indentation problem (incorrect space or tab)
IndexError # Accessing an index outside the bounds of a list or string
KeyError # Key not found in a dictionary
MemoryError # The program has exhausted available memory
ModuleNotFoundError # Python module not found. Keyboard Interrupt # Manually interrupts the NameError # Undefined variable or function
NotImplementedError # Unimplemented method or function
OSError # Error related to the operating system (e.g., permissions problem)
RecursionError # Too many recursions (exceeds the depth limit)
RuntimeError # Generic error not covered by other exceptions
StopIteration # No more elements to iterate over (raised by the iterators)
SyntaxError # Syntax error in the code (missing parentheses, misspelled keyword, etc.)
TypeError # Operation or function applied to an inappropriate type (e.g., adding an integer to a string)
ValueError # Inappropriate value for an operation (e.g., converting a non-numeric string to an integer)
ZeroDivisionError # Division by zero
builtins class errors
ArithmeticError # Base class for arithmetic errors
AssertionError # Assertion failed
AttributeError # Attribute not found
BlockingIOError # I/O operation would block
BrokenPipeError # Broken pipe
BufferError # Buffer error
ChildProcessError # Child process error
ConnectionAbortedError # Connection aborted
ConnectionError # Connection error
ConnectionRefusedError # Connection refused
ConnectionResetError # Connection reset
EOFError # Read beyond end of file
EnvironmentError # Base class for I/O related errors
FileExistsError # File already exists
FileNotFoundError # File not found
FloatingPointError # Floating-point operation failed
IOError # Base class for I/O related errors
ImportError # Import can't find module, or can't find name in module
IndentationError # Improper indentation
IndexError # Sequence index out of range
InterruptedError # Interrupted by signal
IsADirectoryError # Operation doesn't work on directories
KeyError # Mapping key not found
LookupError # Base class for lookup errors
MemoryError # Out of memory
ModuleNotFoundError # Module not found
NameError # Name not found globally
NotADirectoryError # Operation only works on directories
NotImplementedError # Method or function hasn't been implemented yet
OSError # Base class for I/O related errors
OverflowError # Result too large to be represented
PermissionError # Not enough permissions
ProcessLookupError # Process not found
PythonFinalizationError # Operation blocked during Python finalization
RecursionError # Recursion limit exceeded
ReferenceError # Weak ref proxy used after referent went away
RuntimeError # Unspecified run-time error
SyntaxError # Invalid syntax
SystemError # Internal error in the Python interpreter
TabError # Improper mixture of spaces and tabs
TimeoutError # Timeout expired
TypeError # Inappropriate argument type
UnboundLocalError # Local name referenced but not bound to a value
UnicodeDecodeError # Unicode decoding error
UnicodeEncodeError # Unicode encoding error
UnicodeError # Unicode related error
UnicodeTranslateError # Unicode translation error
ValueError # Inappropriate argument value (of correct type)
ZeroDivisionError # Second argument to a division or modulo operation was zero
customize ErrorClass
For module-specific errors, use a prefix: 'class MyModuleError(Exception): ...'
For critical errors, inherit from 'RuntimeError' or 'ValueError'
Inheritance: The class inherits from Exception to be usable as a standard error.
init
Arguments:
- message: Error message (required).
- code: Error code (optional, defaults to 500).
- details: Dictionary for additional information (optional).
str
Displays the error in a readable format.
class CustomError(Exception):
'''Class for a custom error with arguments'''
def __init__(self, message: str, code: int = 500, details: dict = None):
self.message = message
self.code = code
self.details = details or {}
super().__init__(self.message)
def __str__(self):
return f"{self.message} (code: {self.code}, details: {self.details})"
example
try:
raise CustomError("An error has occurred", 404, {"file": "data.txt"})
except CustomError as e:
print(e) # print: "An error has occurred (code: 404, details: {'file': 'data.txt'})"
print(e.code) # print: 404
print(e.details) # print: {'file': 'data.txt'})"
assert
If assert condition return False a AssertionError exception is always launched
- Assertions are primarily used during development.
- It is imperative to avoid side effects in assertions because,
when they are removed, the effect is also removed. - Assertions can be removed from the bytecode if the -O option is called during compilation.
assert condition, "error_message"
# assert is equal to:
if __debug__ :
if not <test> :
raise AssertionError(<values>)static method
if inherited method as redefined, decorator @staticmethod must be added
usefulness
- For utility functions related to the class (e.g., calculations, conversions).
- When the method does not need to access the class or instance's data.
- To avoid cluttering the global namespace with independent functions.
examples
class Sentence:
_call_counter = 0
@staticmethod
def call_counter():
return Sentence._call_counter
def __init__(self, sentence = ''):
Sentence._call_counter += 1
self.sentence = sentence
def __repr__(self):
return f"{__class__} called {self.call_counter()}"
class SentenceLower(Sentence):
_call_counter = 0
@staticmethod
def call_counter():
return SentenceLower._call_counter
def __init__(self, sentence = ''):
SentenceLower._call_counter += 1
self.sentence = sentence.lower()
s1 = Sentence("ma phrase s1")
s2 = SentenceLower("ma phrase s2")
s3 = SentenceLower("ma phrase s3")
print('s1', s1)
>>> s1 <class '__main__.Sentence'> called 1
print('s2', s2)
>>> s2 <class '__main__.Sentence'> called 2
print(s1.call_counter(), Sentence.call_counter())
>>> 1, 1
print(s2.call_counter(), SentenceLower.call_counter())
>>> 2, 2
class method
if inherited method as redefined, decorator @classmethod must be added
usefulness
- Create alternative methods for constructing instances (like factory methods)
- Access or modify class attributes
- Do not depend on a specific instance
class Sentence:
_call_counter = 0
@classmethod
def call_counter(cls):
return cls._call_counter
def __init__(self, sentence = ''):
__class__._call_counter += 1
self.sentence = sentence
def __repr__(self):
return f"{self.__class__} called {self.call_counter()}"
class SentenceLower(Sentence):
_call_counter = 0
def __init__(self, sentence = ''):
__class__._call_counter += 1
self.sentence = sentencehttps://wiki.python.org/moin/PythonDecoratorLibrary
function decorator
A decorator in Python is a function that allows you to modify or extend the behavior of another function or method without altering its source code. It is a powerful tool for adding reusable functionality (such as logging, time measurement, validation, etc.) in a clean and modular way.
@decorator
def my_function(): pass
# is equivalent to
def my_function(): pass
my_function = decorator(my_function)
usefulness
- Custom logging
- Argument validation
- Caching (Memoization)
- Timing
decorator as a class
class without arguments
class CallCounter:
def __init__(self, f):
self.call_counter = 0
self.f = f
def __call__(self, *args, **kargs):
self.call_counter += 1
print(f"{self.f.__name__} : {self.call_counter} call(s)")
return self.f(*args, **kargs)
@CallCounter
def accumulate(*args):
if args and len(args) == 1 and hasattr(args, '__iter__'):
args = args[0]
sum_items = 0
return sum(sum_items := sum_items + i for i in args)
print(accumulate(1,2,3,4,5,6,7,8,9))
>>> accumulate : 1 call(s)
>>> accumulate(10) 165
print(accumulate(range(10)))
>>> accumulate : 2 call(s)
>>> accumulate(10) 165
print(accumulate(range(100)))
>>> accumulate : 3 call(s)
>>> accumulate(10) 166650
class with arguments
class CallCounter:
def __init__(self, step = 1):
self.step = step
self.call_counter = 0
def __call__(self, f):
def wrapper(*args, **kargs):
self.call_counter += self.step
print(f"{f.__name__}: {self.call_counter} call(s)")
return f(*args, **kargs)
return wrapper
@CallCounter(step = 2)
def accumulate(*args):
if args and len(args) == 1 and hasattr(args, '__iter__'):
args = args[0]
sum_items = 0
return sum(sum_items := sum_items + i for i in args)
print(accumulate(1,2,3,4,5,6,7,8,9))
print(accumulate(range(10)))
print(accumulate(range(20)))
decorator as a function
function without arguments
a timer
def mytimer(function):
from datetime import datetime
def wrapper(*args, **kwargs):
d1 = datetime.now()
result = function(*args, **kwargs)
d2 = datetime.now()
print(*args, '->', result)
print('result', result)
print(d2-d1)
return result
return wrapper
@mytimer
def powerful_digit_sum(limit):
max_sum = (2, 2, 1)
for a in range(2, limit):
for b in range(1, limit):
sum_digits = sum(int(i) for i in str(a**b))
max_sum = (sum_digits, a, b) if sum_digits > max_sum[0] else max_sum
return max_sum
limit = 100
powerful_digit_sum(limit)
memoize or cache
def memoize(f):
'''decorator to keep data in cache'''
from functools import wraps
# preserves the metadata of f and not of wrapper. See below functools
@wraps(f)
def wrapper(*args):
try:
return wrapper.cache[args]
except TypeError:
return f(*args)
except KeyError:
result = f(*args)
wrapper.cache[args] = result
return result
# instantiated in module interpretation, before fibo_cache() calling.
# define after function definition
# wrapper is returned to fibo_cache: fibo_cache = memoize(fibo_cache)
wrapper.cache = {}
return wrapper
# @functools.cache # functools.cache is twice as fast. See below
@memoize
def fibo_cache(n):
'''One super-slow fibonacci'''
return n if n <= 1 else fibo_cache(n-1) + fibo_cache(n-2)
print(fibo_cache(100))
>>> 354224848179261915075
print(len(fibo_cache.cache))
>>> 101
print(fibo_cache.__doc__) # thanks to functools.wrap
>>> One super-slow fibonacci
function with arguments
specific cache
def cache_with_size(max_size):
def decorator(f):
cache = {}
def wrapper(*args):
if args in cache:
print("Result retrieved from cache")
return cache[args]
result = f(*args)
if len(cache) >= max_size:
# Remove the first inserted element (FIFO)
cache.pop(next(iter(cache)))
cache[args] = result
return result
return wrapper
return decorator
@cache_with_size(max_size=2)
def expensive_function(x):
print(f"Calculation for {x}...")
return x * x
# Appel
print(expensive_function(2)) # Calculation for 2... → 4
print(expensive_function(3)) # Calculation for 3... → 9
print(expensive_function(2)) # Result retrieved from cache → 4
def memoize_expire(timeout):
'''decorator to keep data in cache with an expiration delay'''
def memoize(f):
import time
from functools import wraps
# preserves the metadata of f and not of wrapper. See below functools
@wraps(f)
def wrapper(*args):
try:
value, timestamp = wrapper.cache[args]
if (time.time() - timestamp) <= timeout:
return value
else:
raise KeyError
except TypeError:
return f(*args)
except KeyError:
value = f(*args)
wrapper.cache[args] = value, time.time()
return value
# instantiated in module interpretation, before fibo_cache() calling.
# define after function definition
# wrapper is returned to fibo_cache: fibo_cache = memoize(fibo_cache)
wrapper.cache = {}
return wrapper
return memoize
# @functools.cache # functools.cache is twice as fast. See below
@memoize_expire(600)
def fibo_cache(n):
'''One super-slow fibonacci'''
return n if n <= 1 else fibo_cache(n-1) + fibo_cache(n-2)
print(fibo_cache(100))
class decorator
A class decorator in Python is a function that allows you to modify or extend the behavior of a class without directly modifying its code. It applies to the class itself, unlike method decorators which apply to methods.
@decorator
class MyClass: pass
# is equivalent to
class MyClass: pass
MyClass = decorator(MyClass)
@decorator(arg)
class MyClass: pass
# is equivalent to
class MyClass: pass
MyClass = (decorator(arg))(MyClass)
usefulness
- Add metadata (version, author, etc.)
- Register classes in a plugin system
- Modify method behavior (logging, validation, etc.)
- Apply mixins dynamically
- Check or validate the class before use
decorator as a function
function without arguments
def has_add(cls):
if not hasattr(cls, '__add__'):
raise AttributeError(f"{cls.__name__} missing attribute: __add__")
return cls
@has_add
class Foo:
'''test class for class decorator'''
def __str__(self):
return f"repr {__class__} !"
f = Foo()
print(f)
function with arguments
def add_field(argdec):
def decorator(cls):
setattr(cls, argdec, 'default')
return cls
return decorator
@add_field('name')
@add_field('address')
class Foo:
'''test class for class decorator'''
def __repr__(self):
return f"{__name__}: name: {self.name} address: {self.address}"
f = Foo()
print(f)
print(f.__doc__)
functools
@wraps
'functools.wraps' is a decorator built into Python's 'functools' module. It is used to preserve the metadata of an original function when it is decorated by another function (a wrapper).
import functools
@functools.cache
def my_function():
pass
@cache
import functools
@functools.cache
def my_function():
pass
@lru_cache
import functools
@functools.lru_cache(maxsize=128, typed=False)
def my_function():
pass
decorators' collection
install
pipx
sudo pacman -S python-pipx # archlinux, manjaro, ...
sudo apt-get install pipx # ubuntu, debian, ...
pipx install pipenv
pip
sudo pacman -S python-pipx # archlinux, manjaro, ...
sudo apt-get install python3-pip # ubuntu, debian, ...
pip install pipenv
use
mkdir my_project
cd my_project
pipenv --version # show program's version number and exit
pipenv --python <version> # install Python version if its available (use pyenv)
pipenv install requests # required packages
pipenv install numpy matplot ... # install pip packages
pipenv run pip list # List all pip installed packages
pipenv graph # Display currently-installed dependency graph information
pipenv uninstall <package> # remove pip package from virtualenv
pipenv shell # Spawn a shell within the virtualenv
pipenv run python script.py # Spawn a command installed into the virtualenv
pipenv --where # Output project home information.
pipenv --venv # Output virtualenv information.
pipenv --py # Output Python interpreter information
pipenv requirements # Generate a requirements.txt from Pipfile.lock
Pipfile : Liste des dépendances et des packages en développement
Pipfile.lock : Version exacte des dépendances installées (pour la reproductibilité)
pipenv remove # Remove the virtualenv for the current project
cd my_project && rm Pipfile Pipfile.lock # delete files from project directory
pipx install --user --upgrade pipenv # update the packages regularly
eclipse
packages
pipenv install matplot modtools numpy pandas setuptools sympy
configuration
- select Windows/Preferences/Pydev/Interpreters/Python interpreter
- New/New with pipenv
- select the path given by 'pipenv --where' for the first field: 'Project location'
- click directly on 'create Pipenv interpreter'
install
sudo pacman -S tk pyenv # archlinux, manjaro, ...
sudo apt-get install pyenv python3-tk # ubuntu, debian, ...
use
pyenv versions # list all installed Python version(s)
pyenv install --list # list all available Python versions
pyenv install <version> # install a specific Python version
pyenv version # Show the current Python version(s) and its origin
pyenv version-file # Detect the file that sets the current pyenv version
pyenv version-name # Show the current Python version
pyenv version-origin # Explain how the current Python version is set
pyenv uninstall <version> # Uninstall Python version
pyenv global # Set or show the global Python version(s)
pyenv local # Set or show the local application-specific Python version(s)
pyenv exec # Run an executable with the selected Python version
pyenv shims # List existing pyenv shims
pyenv whence # List all Python versions that contain the given executable
pyenv which # Display the full path to an executableexport LIBVIRT_DEFAULT_URI=qemu:///system # for virsh autoconnection
pth=/vms/virt
domain=cuckoo-1804
newdomain=cuckoo-1804-clone
pthdisk=$pth/${domain}.qcow2
pthnewdisk=$pth/${domain}-clone.qcow2
pthtmp=/vms/share/${domain}-${date +%s}
lssnapshot=$(virsh snapshot-list $domain --name)
[ -d ${pthtmp} ] || mkdir -p ${pthtmp}
# dump snapshots
for snapshot in ${lssnapshot}; do
virsh snapshot-dumpxml --domain ${domain} ${snapshot} > ${pthtmp}/${domain}_${snapshot}.xml
done
# create a volatily image
sudo qemu-img create -f qcow2 ${pthnewdisk} 100M
# clone domain
virt-clone --original ${domain} --name ${newdomain} --file ${pthnewdisk} --preserve-data
# restore snapshots to empty disk
for snapshot in ${lssnapshot}; do
virsh snapshot-create ${newdomain} --xmlfile ${pthtmp}/${domain}_${snapshot}.xml --atomic
done
# verify snapshots list
echo "- domain snapshots:"
virsh snapshot-list ${newdomain}
# full copy disk / qemu-img convert loses snapshots
sudo cp -a ${pthdisk} ${pthnewdisk}
# verify image snapshots list
echo "- disk snapshots:"
qemu-img snapshot -l ${pthnewdisk}
echo "Launch domain ${newdomain} in virt-manager (restart virt-manager)MASTER
echo -e -n "Give the domain name: " && read domain
echo -e -n "Give the path of pool (/vms/virt) : " && read pth_pool
pth_pool=${pth_pool:-/vms/virt}
echo -e -n "Give the path of disk ($pth_pool/${domain}.qcow2) : " && read pth_disk
pth_disk=${pth_disk:-$pth_pool/${domain}.qcow2}
pth_pool=/vms/virt
domain=cuckoo-1804
pth_disk=$pth_pool/${domain}.qcow2
sdate=$(date +%s)
pth_xml=/vms/share/${domain}-${sdate}
export LIBVIRT_DEFAULT_URI=qemu:///system # for virsh autoconnection
[ -d ${pth_xml} ] || mkdir -p ${pth_xml}
# dumps
echo "> ${domain}"
virsh dumpxml ${domain} > ${pth_xml}/${domain}.xml
for snapshot in $(virsh snapshot-list $domain --name); do
echo " ${snapshot}"
virsh snapshot-dumpxml --domain ${domain} ${snapshot} > ${pth_xml}/${domain}_${snapshot}.xml
done
pth=/tmp/${domain}::${sdate}.tar.gz
cd ${pth_xml}
tar czf ${pth} *
echo -e "\nPlease copy this files to slave:"
echo ${pth}
echo ${pth_disk}
SECOND
echo -e -n "Give the path of snapshots compressed files: " && read pth_tgz
echo -e -n "Give the path of copied disk: " && read pth_disk
echo -e -n "Give the path of pool (/vms/virt) : " && read pth_pool
pth_pool=${pth_pool:-/vms/virt}
export LIBVIRT_DEFAULT_URI=qemu:///system # for virsh autoconnection
domain=${pth_tgz##*/}; domain=${name%::*}
sdate=${pth_tgz##*::}; sdate=${sdate%%.*}
pth_disk=${pth_pool}/${domain}.qcow2
pth_xml=/vms/share/${domain}-${sdate}
[ -d "${pth_xml}" ] || mkdir -p "${pth_xml}"
tar xzf ${pth_tgz} -C "${pth_xml}"
# create a volatily image
sudo qemu-img create -f qcow2 ${pth_disk} 100M
# define domain
virsh define ${pth_xml}/${domain}.xml
virt-clone --original ${domain} --name ${domain} --file ${pth_disk} --preserve-data
# restore snapshots to empty disk
for snapshot in ${lssnapshot}; do
virsh snapshot-create ${domain} --xmlfile ${pth_tmp}/${domain}_${snapshot}.xml --atomic
done
# verify snapshots list
echo "- domain snapshots:"
virsh snapshot-list ${domain}
# full copy disk / qemu-img convert loses snapshots
if ! [ "${pth_disk%%/*}" = /vms/virt ]; then
echo "copy disk from '${pth_disk}' to '/vms/virt/${pth_disk##*/}'"
sudo cp -a ${pth_disk} ${pth_disk}
fi
# verify image snapshots list
echo "- disk snapshots:"
qemu-img snapshot -l ${pth_disk}
echo "Launch domain ${domain} in virt-manager (restart virt-manager)/etc/libvirt/qemu/: path of xml domain files
connect
export LIBVIRT_DEFAULT_URI=qemu:///system # to use sumply virsh <command>
virsh -c qemu:///system # enter in virsh console
virsh -c qemu:///system <command> # execute only a virsh command (needed for dumping to file)
help
help # list all commands with a one line description
help <command> # show complete description & options
domains
monitor
domblkerror # Show errors on block devices
domblkinfo # domain block device size information
domblklist # list all domain blocks
--inactive # get inactive rather than running configuration
--details # additionally display the type and device value
domblkstat # get device block stats for a domain
domcontrol # domain control interface state
domif-getlink # get link state of a virtual interface
domifaddr # Get network interfaces' addresses for a running domain
domiflist # list all domain virtual interfaces
domifstat # get network interface stats for a domain
dominfo # domain information
dommemstat # get memory statistics for a domain
domstate # domain state
domstats # get statistics about one or multiple domains
domtime # domain time
list # list domains
--state-running
--inactive # list only all inactive domains
--state-shutoff
--all # list all domains
--with-snapshot # list domains with existing snapshot
--without-snapshot # list domains without a snapshot
--with-checkpoint # list domains with existing checkpoint
--without-checkpoint # list domains without a checkpoint
others
attach-disk <domain> <source> <target> # attach-disk <domain> <source> <target>
--targetbus <string # target bus of disk device
--driver <string> # driver of disk device
--subdriver <string> # subdriver of disk device
--iothread <string> # IOThread to be used by supported device
--cache <string> # cache mode of disk device
--io <string> # io policy of disk device
--type <string> # target device type
--mode <string> # mode of device reading and writing
--sourcetype <string> # type of source (block|file|network)
--serial <string> # serial of disk device
--wwn <string> # wwn of disk device
--alias <string> # custom alias name of disk device
--rawio # needs rawio capability
--address <string> # address of disk device
--multifunction # use multifunction pci under specified address
--print-xml # print XML document rather than attach the disk
--source-protocol # <string> protocol used by disk device source
--source-host-name # <string> host name for source of disk device
--source-host-transport # <string> host transport for source of disk device
--source-host-socket <string> # host socket for source of disk device
--persistent # make live change persistent
--config # affect next boot
--live # affect running domain
--current # affect current domain
create <file> # create a domain from an XML file
--console # attach to console after creation
--paused # leave the guest paused after creation
--autodestroy # automatically destroy the guest when virsh disconnects
--pass-fds <string> # pass file descriptors N,M,... to the guest
--validate # validate the XML against the schema
--reset-nvram # re-initialize NVRAM from its pristine template
define <file> # define (but don't start) a domain from an XML file
--validate # validate the XML against the schema
detach-disk <domain> <target> # detach disk device (target is the device name in domain)
--persistent # make live change persistent (use to detach when the domain is inactive)
--config # affect next boot
--live # affect running domain
--current # affect current domain
--print-xml # print XML document rather than detach the disk
dumpxml <domain> # Output the domain information as an XML dump to stdout
--inactive # show inactive defined XML
--security-info # include security sensitive information in XML dump
--update-cpu # update guest CPU according to host CPU
--migratable # provide XML suitable for migrations
pool
# list
pool-list # list pools
--inactive # list inactive pools
--all # list inactive & active pools
--autostart # list pools with autostart enabled
--no-autostart # list pools with autostart disabled
--type <string> # only list pool of specified type(s) (if supported)
--details # display extended details for pools
--uuid # list UUID of active pools only
--name # list name of active pools only
# info
pool-info <pool> # storage pool information
# refresh
pool-refresh # refresh a pool
volume
# list
vol-list <pool> # list volumes from a pool
--details # display extended details for volumes
# info
vol-info <vol> <pool> # show storage volume informations
vol-info --pool <pool> <vol>
# clone
vol-clone --pool <pool> <vol> <clonevol> # Clone an existing volume within the parent pool
--prealloc-metadata # preallocate metadata (for qcow2 instead of full allocation)
--reflink # use btrfs COW lightweight copy
# delete
vol-delete --pool <pool> <vol> # delete a vol
--delete-snapshots # delete snapshots associated with volume (must be supported by storage driver)
# upload
vol-upload --pool <pool> <vol> <file> # upload (import) file contents to a volume
# dumpxml
vol-dumpxml --pool <pool> <vol> # output the vol information as an XML dump to stdout
virsh vol-dumpxml <vol> <pool> > <file> # dump into file
# wipeexport LIBVIRT_DEFAULT_URI=qemu:///system
vol-wipe --pool <pool> <vol> # wipe a vol. Ensure data previously on a volume is not accessible to future reads
--algorithm <string> # perform selected wiping algorithm (ex: zero, nnsa, dod, pfitzner7, pfitzner33, random)
# key
vol-key --pool <pool> <vol> # returns the volume key for a given volume name or path
# path
vol-path --pool <pool> <vol> # returns the volume path for a given volume name or key
--pool <string> # pool name or uuid
--offset <number> # volume offset to upload to
--length <number> # amount of data to upload
--sparse # preserve sparseness of volume
backup
# dumpxml
backup-dumpxml <domain> # Dump XML for an ongoing domain block backup job
# backup
backup-begin <domain> # Start a disk backup of a live domain. Use XML to start a full or incremental disk backup of a live domain, optionally creating a checkpoint
--backupxml <string> # domain backup XML
--checkpointxml <string> # domain checkpoint XML
--reuse-external # reuse files provided by caller
snapshot
# list
snapshot-list <domain> # list all snapshots from a domain (domain name, id or uuid)
--tree # list snapshots in a tree
--current # limit list to children of current snapshot
--name # list snapshot names only
--parent # add a column showing parent snapshot
--roots # list only snapshots without parents
--leaves # list only snapshots without children
--no-leaves # list only snapshots that are not leaves (with children)
--metadata # list only snapshots that have metadata that would prevent undefine
--no-metadata # list only snapshots that have no metadata managed by libvirt
--internal # filter by internal snapshots
--external # filter by external snapshots
--from <snapshot> # limit list to children of given snapshot
--descendants --from <snapshot> # list all descendants from one snapshot
--descendants --current
# info
snapshot-info <domain> <snapshot> # show snapshot informations (domain name, id or uuid)
# revert
snapshot-revert <domain> [<snapshot>] # Revert a domain to a snapshot
--snapshotname <snapshot> snapshot name
--current # revert to current snapshot
--running # after reverting, change state to running
--paused # after reverting, change state to paused
--force # try harder on risky reverts
--reset-nvram # re-initialize NVRAM from its pristine template
# dumpxml
snapshot-dumpxml --domain <domain> <snapshot> # dump snapshot definition to stdout
--domain <domain> # domain name, id or uuid
--security-info include security sensitive information in XML dump
virsh snapshot-dumpxml --domain <domain> <snapshot> > <file> # dump into file
tricks
dumpxml all domains
pthxml=/vms/virt/xml-$(date "+%Y%m%d")
# xml
! [ -d ${pthxml} ] && sudo mkdir -p ${pthxml} && sudo chown 1000:1000 ${pthxml}
echo "--> ${pthxml}"
for domain in $(virsh list --all --name); do
echo "> ${domain}"
virsh dumpxml ${domain} > ${pthxml}/${domain}.xml
for snapshot in $(virsh snapshot-list $domain --name); do
echo " ${snapshot}"
virsh snapshot-dumpxml --domain ${domain} ${snapshot} > ${pthxml}/${domain}:${snapshot}.xml
done
done
export all domains & insternal snapshots to appliances
pthpool=/vms/virt
pthapl=${pthpool}/appliances
pthxml=${pthpool}/xml-$(date "+%Y%m%d")
which pigz || { echo "Install pigz"; exit; }
cd ${pthpool} || { echo "Unable to enter in ${pthpool}"; exit; }
for pth in ${pthxml} ${pthxml}; do sudo mkdir -p ${pth} && sudo chown 1000:1000 ${pth}; done
for domain in $(virsh list --all --name); do
echo "> ${domain}"
virsh dumpxml ${domain} > ${pthxml}/${domain}.xml
for snapshot in $(virsh snapshot-list $domain --name); do
echo " ${snapshot}"
virsh snapshot-dumpxml --domain ${domain} ${snapshot} > ${pthxml}/${domain}:${snapshot}.xml
done
file=${pthapl##*/}/${domain}-$(date "+%Y%m%d").tar.gz
echo ">>> ${file}"
tar -cI pigz -f ${file} ${domain}.qcow2 ${pthxml##*/}/${domain}.xml ${pthxml##*/}/${domain}:*.xml
done
sudo chown 1000:1000 -R ${pthapl}
clone domain with internal snapshots
See: virsh - migrate
migrates domain to another host with internal snapshots
See: virsh - clone
Ubuntu
extract deb files
file=mudita24_1.0.3+svn13-7build3_amd64.deb
pth=${file%\.*}
mkdir -p ${pth}/data && ar x --output=${pth} ${file}
tar -xf ${pth}/data.tar.zst -C ${pth}/data
tree ${pth}/data # to view contentsCommands
dconf list /<path>[:]/
dconf read /<path>[:]/<key>
dconf write /<path>[:]/<key> "<value> <value> ..."
dconf dump /<path>[:]/ > <file>
dconf load /<path>[:]/ < <file>
Tricks
profiles
# list
dconf list /org/gnome/terminal/legacy/profiles:/ # list all profiles
dconf list /org/gnome/terminal/legacy/profiles:/:1d5ff56e-96be-4d97-84c1-99a625d4054e/ # list all keys
# keys/values
dconf read /org/gnome/terminal/legacy/profiles:/:1d5ff56e-96be-4d97-84c1-99a625d4054e/background-color # read values for key background-color
# dump profiles
dconf load /org/gnome/terminal/legacy/profiles:/ > <file> # dump gnome-terminal profiles
dconf dump /org/gnome/terminal/legacy/profiles:/nikita/ > <file> # dump gnome-terminal profile for user nikita
# load profiles
dconf load /org/gnome/terminal/legacy/profiles:/ < <file> # load all profiles
dconf load /org/gnome/terminal/legacy/profiles:/<profil>/ < <file> # load a user profile
screensaver
dconf write /org/gnome/desktop/screensaver/lock-delay "uint32 3600" # set delaying screensaver to 3600sInstall
https://virtualenv.pypa.io/en/latest/installation.html
manjaro
sudo pacman -S --needed python python-pipx
pipx install virtualenv
Use
https://virtualenv.pypa.io/en/latest/cli_interface.html#creator
virtualenv <path> # create the virtual environment in <path>
virtualenv --creator <path> # create the virtual environment in <path> with specific creator like : cpython3-mac-brew, cpython3-mac-framework, cpython3-posix, cpython3-win, graalpy-posix, graalpy-win, pypy3-posix, pypy3-win, venv
<path>/bin/activate # activate the virtual environment
deactivate # deactivate the virtual environment
which python3 # to view the referred python pahUsefull
options
-graft-points Allow to use graft points for filenames
-J, -joliet Generate Joliet directory information
-o FILE, -output FILE Set output file name
-quiet Run quietly
-r, -rational-rock Generate rationalized Rock Ridge directory information
-R, -rock Generate Rock Ridge directory information
-root DIR Set root directory for all new files and directories
commands
mkisofs -Jr -o <file> <path> <pat2h> ... # create an iso file from paths
mkisofs -Jr -o <file> -graft-points /<virtualpath1>=/<physicalpath1> /<virtualpath2>=/<physicalpath2> ... # create an iso file from paths with corresponding virtualpath=physicalpath
# create an iso file 'desktop-install.iso' with virtual paths: /bs, /desktop-manjaro and /desktop-ubuntu
mkisofs -Jr -o /vms/iso/desktop-install.iso -graft-points /bs=/home/shared/repo/bs /desktop-manjaro=/home/shared/repo/desktop-manjaro /desktop-ubuntu=/home/shared/repo/desktop-ubuntu /desktop-debian=/home/shared/repo/desktop-debianlock/unlock
faillock
faillock --user nikita # show failed login
faillock --reset --user nikita # reset the number of failed login. Allow to login after pam restrict access for example "too many tries"
passwd
passwd --status # show status of user <user>
passwd -S <user>
passwd --lock <user> # lock user <user>
passwd -l <user>
passwd --unlock <user> # unlock user <user>
passwd -u <user>
usermod
usermod --lock <user> # lock user <user>
usermod -L <user>
usermod --unlock <user> # unlock user <user>
usermod -U <user>TRICKS
create a local git repository and publish it to github
- create the repo on github
- on local repo:
cd <my_local_repo> git init echo "# <my_local_repo>" >> README.md git commit -m "first commit: Initialize repo" git co main git remote add [-t <branch>] -m main [--mirror=(fetch|push)] <name> <URL> # git remote add -m main github git@github.com:aguytech/docker_alpine-alias.git git remote -v git push -u <name> main # for only main git push --all -u <name> main # for all branches # git push -u github main
connection with ssh
- import public key to github
- test
ssh -T -i $private_key_file git@github.com # test ssh connection ssh -T -i $private_key_file -p 443 git@ssh.github.com # test ssh connection over https ssh-add $private_key_file # avoids the repeated entry of secret phrases - set the default key
git config --global user.signingkey $privaye_key_file # for ssh - test with git command
GIT_SSH_COMMAND="ssh -i $privaye_key_file -vvv" git pull
change remote url for remote existing repository
git remote -v # print https://github.com/user/project
git remote set-url origin git@github.com:user/project.git # change the connection url to use ssh
git remote -v # print git@github.com:user/project.git
delete tags
git tag -d [tag];
git push origin :[tag]
git tag -d [tag]
git push origin :refs/tags/[tag]
create orphan repo from another
Create origin to remote server
repo_local="shaarli-snippets"
tmp_branch="dev"
origin="github"
url_origin="git@github.com:aguytech/Shaarli-snippets.git"
upstream="shaarli"
url_upstream="git@github.com:aguytech/Shaarli.git"
upstream_branch="v0.11-snippets" # remote branch to track
mkdir -p "$repo_local"
cd "$repo_local"
git init
# remote
git remote add "$origin" "$url_origin"
git remote add -t "$upstream_branch" "$upstream" "$url_upstream"
git remote -v
git config --get-regexp '^remote'
# upstream
git fetch "$upstream"
git co --orphan="$tmp_branch" "$upstream"/"$upstream_branch"
git st
git ci -m "Initialize branch from $upstream/$upstream_branch $(git log --pretty=format:'%h' -n 1 "$upstream"/"$upstream_branch")"
# origin
git push --set-upstream "$origin" "$tmp_branch"
git co -b master
git push --set-upstream "$origin" master
git br -vv
git br -rlv github/*
# archive
git archive --format tar.gz -9 -o "master.$(date +%s).tar.gz" master