Get file commit time in GitPython - python-3.x

How we can get the commit time of file (blob) via Gitpython while traversing the tree?
I need to get commit time of each FILE (not directory) in the full repo/tree. Something as we get via command git log -1 --pretty="format:%cI" <file_path>
repo = git.Repo('some_repo')
tree = repo.tree().traverse()
for blob in tree:
print(blob.path)
if os.path.isfile(blob.abspath):
# get commit_time of blob something like 'git log -1 --pretty="format:%cI" blob.path'
# this works but create mess with environment
# os.popen(f'git log -1 --pretty="format:%cI" {str(blob.path)}').read()
I tried by traversing the full directory with pathlib.Path then passing the git directory by command git -C <path_to_git_dir> log -1 --pretty="format:%cI" <file_path>, but it created mess as this code has to be run within another git repository , hence preferred using gitPython not via git from environment.

Related

Cannot git pull due CONFLICT(MODIFY/DELETE) and symlink

Our Laravel project is using symlinks. Recently when I tried to pull from my colleague's work, I get this message:
CONFLICT (modify/delete): resources/lang/en/validation.php deleted in HEAD and modified in a262067feb430a072c1d3abf2ec500150212ff0f. Version a262067feb430a072c1d3abf2ec500150212ff0f of resources/lang/en/validation.php left in tree.
error: failed to symlink 'resources/lang/en/validation.php': File name too long
Upon trying to git rm the file, I am told it doesn't exist and is deleted in HEAD. Then when I pull I get the same message as above. Upon trying to touch the file and git add the file, and commit and then pull (in order to push my changes to the same branch), I get a similar error message:
CONFLICT (content): Merge conflict in resources/lang/en/validation.php
CONFLICT (modify/delete): resources/lang/en/auth.php deleted in HEAD and modified in a262067feb430a072c1d3abf2ec500150212ff0f. Version a262067feb430a072c1d3abf2ec500150212ff0f of resources/lang/en/auth.php left in tree.
error: failed to symlink 'resources/lang/en/auth.php': File name too long
I have tried to skip-worktree the file, assume-unchanged the file and to change the git config setting via git config --local core.longpaths true to allow long-paths. None have worked. I think it has to do with the symlink, but I haven't run the script yet and so I don't know how this is a barrier to pulling for git.
When I do try to run the symlink, I get this error message:
error: unable to create symlink resources/lang/en/auth.php: File name too long
error: unable to create symlink resources/lang/en/validation.php: File name too long
Long story short, I cannot git pull, and therefore cannot git push. What's the solution? I don't want to git push force it.
Running git pull is just running two Git commands:
First, git pull runs git fetch. This obtains any new commits needed for the second command.
Second, git pull runs ... well, this can be complicated. You are having it run the default, though: git merge.
Usually when git pull fails, one of these two commands that it runs is the one that actually failed. The second command fails more often unless you have a particularly flaky Internet connection. In your case, it's the git merge that failed.
The word failed is usually too strong, really. Most merges do not actually fail. They just stop in the middle of the operation due to a conflict (or two conflicts, in your particular case). But your merge is a little special. It really does have an internal failure, which repeats several times:
error: unable to create symlink resources/lang/en/auth.php: File name too long
error: unable to create symlink resources/lang/en/validation.php: File name too long
This is happening because your OS is placing a hard limit on the length of the target of a symbolic link. As you found:
It seems it was trying to make a symlink out of the content inside the file instead of the file name ...
Git's internal limits are much bigger than your OS's.
A symbolic link is just data, at one level, and that's how Git tends to store it (as a blob object, but one with mode 120000 rather than the normal file mode of 100644 or 100755). At another level, the data will be interpreted as a file name, and that file name tends to have a length limit, such as 1024 or 4096 bytes.
What would git show do?
git show will spill out the contents of the symlink, when pointed to a symbolic-link object.
$ git hash-object -w -t blob /usr/share/misc/termcap
d305cd8e161ecc8a78b0485d1926b9600efc6cb7
$ git update-index --add --cacheinfo 120000,d305cd8e161ecc8a78b0485d1926b9600efc6cb7,crazy
$ git commit -m "add crazy-long symlink"
[master dbb6e35] add crazy-long symlink
1 file changed, 4725 insertions(+)
create mode 120000 crazy
The normal tools will no longer work with this repository (which I made just to hold this crazy-long symlink):
$ git log | sed 's/#/ /'
commit dbb6e35967041fa4b03812866999ea0acd640dce
Author: Chris Torek <chris.torek gmail.com>
Date: Sun Nov 15 19:52:05 2020 -0800
add crazy-long symlink
commit c6e238c122dcd41410e7fdcfaa47ac112e935a35
Author: Chris Torek <chris.torek gmail.com>
Date: Sun Nov 15 19:51:58 2020 -0800
initial commit
$ git checkout HEAD^
This works fine, but trying to check out the second commit fails:
$ git checkout master
error: unable to create symlink crazy: File name too long
D crazy
Previous HEAD position was c6e238c initial commit
Switched to branch 'master'
What happens at this point is that Git simply leaves the symbolic link out of the working tree entirely. That's why it is in state D. You can still do work with the repository, but you cannot use the regular tools in the regular way.
With your merge, what you can do is delete the bad symbolic links entirely (safely), create correct (good) ones, and add them.

Copy files task is not copying to Azure repos

I have a inventory.txt in one folder of my azure repos. I need to copy that to another folder. I have used "Copy File task" but it copying file to the required folder only in agent machine.Its not reflecting in azure repos. What Can I do.
My Main Task is to give a packages_list variable in a inventory file. But this variable is being used by two yaml files which are two different folders and used for two different pipeline. For that I have declared a packages_list variable in one of the folder and copy to another folder. ANy other alternativeees are much appreciated.
After copy the files to target folder, you need run git command to push changes to sync the changed folder back into Azure devops repo.
Please try with below steps to configure your pipeline:
(1) The first Command line task:
git config --global user.email "xxx#xx.com"
git config --global user.name "Merlin"
cd $(Build.SourcesDirectory)
git init
(2) In second task, execute the Copy file task.
(3) In next Command line task, do git push to push the changes:
git add .
git commit -m "File copied"
git remote rm origin
git remote add origin https://xxx#dev.azure.com/xxx/xxx/_git/xxxx
git push -u origin HEAD:master
Since above command is modifying Azure repos, please enable Allow scripts to access the OAuth token in agent job and ensure the corresponding Build service account has Contribute permission to Git repos. Just follow this doc to configure the permission setting.

How to use Custom Hooks with GitLab CE on Ubuntu 20.04 - VPS?

RESUME
When I push from my local workspace to the target repo in GitLab on my remote VPS, I want GitLab run a script and ask a beta repo on the same VPS to git checkout and pull in order to check my changes.
Current configurations
Gitlab configurations
Suppose you already have a project in your admin area, you just need to get it's relative path
Admin area > Projects
Select your project
Get the path in the project profil (hashed for this case)
Create a new directory in this location called custom_hooks.
sudo su
cd /var/opt/gitlab/git-data/repositories/hashed/path/of/project
mkdir custom_hooks
Inside the new custom_hooks directory, create a file with a name matching the hook type. For a post-receive hook the file name should be post-receive with no extension.
cd custom_hooks
nano post-receive
Write the code to make the server hook function as expected. Hooks can be in any language. Ensure the ‘shebang’ at the top properly reflects the language type. In that case the script code used is :
#!/bin/sh
unset GIT_INDEX_FILE
cd /var/repo/beta.git && git checkout master && git up # --[see the note 2 below]
Make the hook file executable and make sure it’s owned by Git.
chmod +x post-receive
Note 1 :
You can find more informations about git hooks here : GitLab Documentation : Server hooks
VPS configurations
Create new alias with #RichardHansen recommandations
git config --global alias.up '!git remote update -p; git merge --ff-only #{u}'
Note 2 :
During my researches, I've found an interesting answer about git pull on the forum.
I've decided to follow that advice and I made an alias named git up.
What is important is that :
it works with all (non-ancient) versions of Git,
it fetches all upstream branches (not just the branch you're currently working on), and;
it cleans out old origin/* branches that no longer exist upstream.
You can find more informations about "In what cases could git pull be harmful ?" here :
Link to answer
Create a directory for git repos only and access it to process Hooks configurations
# Create a repo for the project in apache area
mkdir /var/www/beta
# Create the git repo only folder
cd /var
mkdir repo && cd repo
# Create git repo and init
mkdir beta.git && cd beta.git
git init --bare # --bare means that our folder will have no source files, just the version control.
# Add gitlab remote
git remote add gitlab
# Accessing hooks folder to create script
cd hooks
cat > pre-receive
# On the blank line, write this script then 'ctrl + d' to save and press enter to exit
#!/bin/sh
unset GIT_INDEX_FILE
git --work-tree=/var/www/beta --git-dir=/var/repo/beta.git checkout -f
# Make the file executable
chmod +x post-receive
Note 3 :
'git-dir' is the path to the git repository. With 'work-tree', we can define a different path to where the files will actually be transferred to.
The 'post-receive' hook will be looked into every time a push is completed and will set the path where the files will be transferred to /var/www/beta in that case.
Local Workspace configurations
# Create in your workspace a folder to hold the project
cd /path/to/workspace
mkdir project && cd project
# Initialize git and add gitlab remote
git init
git remote add gitlab ssh://user#mydomain.com/gitlab/path/of/project
# Create an index.html file and send the initial commit
nano index.html
# copy this into the file then 'ctrl + x' then 'y' then 'enter' to save
<html>
<head>
<title>Welcome to Beta domain!</title>
</head>
<body>
<h1>Success! The beta virtual host is working!</h1>
</body>
</html>
# prepare the changes and then send the commit
git status
git add index.html
git commit -m "chore: add index.html :tada: :rocket:"
git push gitlab master
EXPECTED RESULTS
The expected result of this process is that when the git push gitlab master is done, the hook inside the gitlab hashed directory of the project, run a script who make something like this :
# Access the beta.git directory
cd /var/repo/beta.git
# Run command for updating repo
git checkout master && git up
# If we access the beta folder in apache area we should see index.html
cd /var/www/beta
ls
--index.html
ACTUAL RESULTS
No result.
ERROR MESSAGES
No error messages.
REQUEST
How can I set up a process like this one ?
There is something in my process I did not take in consideration ?

How do I make git branch work when some git file or directory lost?

One day I change a vim configuration from Github(https://github.com/ma6174/vim) on Linux(Visualbox Ubuntu), then some git orders doesn't work.e.g.:
git diff
diff-so fancy | less --tabs = 4 RFX: 1: diff-so fancy | less -- tabs = 4 RFX: diff-so:not found 4: No such file or directory
RFX: No such file or directory
Also when I input git branch, git log, it's doesn't work.Just give me something wrong.
But I can use git add ,git commit -m "", git push to push my file to the remote repository.I also can create a new branch, while can't check the information about dev or master.
Please tell me how to let git work normally.

Unable to use git send-email to send source code and patches

I have a directory created locally: /home/Tegra.
I have created following Files inside /home/Tegra:
hello_world.c hello_world_1.c hello_world_2.c
Each file is incrementally modified. I have also created patches as:
diff -u hello_world.c hello_world_1.c > hello_world_1.patch
diff -u hello_world_1.c hello_world_2.c > hello_world_2.patch
Now I want to first send an email using git send-email to email address abc#xyz.org. which should contain hello_world.c file
Then I want to send second email with hello_world_1.patch file as attachment.
Then I want to send third email with hello_world_2.patch file as attachment.
Unfortunately, I am not even able to do the step 1:
My git has been properly configured with relevant smtp server tls 587 port.
I tried following command:
git send-email --to abc#xyz.org --subject My Hello hello_world.c
I get following error:
Cannot run git format-patch from outside a repository
Where does repository come into picture. SHould I have to maintain first a repository of my code.
Edit: For step 1: As per comments below we need a repository:
Created a Empty Repository on Github : "MyRepo"
Cloned it on local machine. (using git clone )
Then added the first file "hello_world.c" into the Directory /MyRepo".
Then >>git add hello_world.c
Then >>git commit -m 'My First source'
Then >>git push -u origin master
After that, I typed: git send-email --to=abc#xyz.org --subject="[asdasdas] assd asdasd" hello_world.c
Now I get an Error:
No subject line in hello_world.c ? at /usr/lib/git-core/git-send-email line 584
Then added the first file "hello_world.c" into the Directory /MyRepo".
First make sure you have actually committed anything in your cloned empty repo.
git add .
git commit -m "new commit"
git push
Second, the git send-email doc does mention:
--subject=<string>
Specify the initial subject of the email thread. Only necessary if --compose is also set.
Make sure to use --compose.
This format expects the first line of the file to contain the "Cc:" value and the "Subject:" of the message as the second line.
That would work with a .patch, not the source itself.
See git format-patch, and "How to send patches with git-send-email" for a more complete example:
For the last commit:
git send-email -1 --to=abc#xyz.org --subject="[asdasdas] assd asdasd"
Third, a simpler solution would be to use git bundle. That generates one file that you can send any way you want, and from which the receiver can pull/clone from. It acts (that one file) as a bare git repo.

Resources