GitPython: How to git clone inside directory without providing the full path? - gitpython

When i do a git clone from the command line, It automatically creates a new directory with the name of that repository and puts the code inside that directory.
But when i do
from git import Repo
Repo.clone_from('https://github.com/jessfraz/dockerfiles.git', '/home/dev')
i get this
GitCommandError: Cmd('git') failed due to: exit code(128)
cmdline: git clone -v https://github.com/jessfraz/dockerfiles.git /home/dev
stderr: 'fatal: destination path '/home/dev' already exists and is not an empty directory.
How can i get the repository name and build the path /home/dev/<repo_name> ?

I just had a look at the code and I think you need to provide the full path to your working copy (i.e. /home/dev/dockerfiles).
If you don't want that, you might need to create your own Repo class inherited from the origin Repo class. You might then want to overwrite the clone_from() class method. Something like this (not tested, just a quick draft):
from git import Repo
class YourRepo(Repo):
#classmethod
def clone_from(cls, url, to_path=None, **kwargs):
if to_path is None:
to_path = url.split('/')[-1]
if to_path.endswith('.git'):
to_path = to_path[0:-4]
return super().clone_from(url=url, to_path=to_path, **kwargs)

Related

go mod init with private bitbucket repositories, contains disallowed path separator character ':'

Using:
% go version
go version go1.16.4 darwin/amd64
I've got a private bitbucket.org repository with a url like:
git#bitbucket.org:chmorgan/some_repo.git
Per the bitbucket url format you would do 'git clone git#bitbucket.org:chmorgan/some_repo.git' to clone it and cloning works fine.
When I try to make a new module I get:
go mod init git#bitbucket.org:chmorgan/some_repo.git
go: invalid module path "git#bitbucket.org:chmorgan/some_repo.git": contains disallowed path separator character ':'
Note that I've already configured git in ~/.gitconfig:
[url "git#bitbucket.org:"]
insteadOf = https://bitbucket.org/
This used to work with earlier golfing versions, I think it worked with golang 1.12 or 1.13. Anyone know what's up?
The argument to go mod init is the “module path”, which is used as a prefix of the package import path for every package within the module. As a result, the argument to go mod init must be valid as a package import path.
(See https://golang.org/doc/code for more detail.)
The package import path we would normally use for a repo cloned from git#bitbucket.org:chmorgan/some_repo.git is bitbucket.org/chmorgan/some_repo.

Hugo not using local git config

I'm trying to use a private theme/module with a personal access token. I can get this working by adding the following to my global git config.
git config --global url."https://{USER}:{TOKEN}#github.com".insteadOf "https://github.com"
Then running hugo mod get -u it will pull changes as expected.
I don't want this set in my global config and if I set it locally I get an error, because Go doesn't seem to be using the local config.
Set my configurations locally within the root of the site/repository:
git config --local url."https://{USER}:{TOKEN}#github.com".insteadOf "https://github.com"
Then running hugo mod get -u I get the following error:
go get: module github.com/USER/REPOSITORY: git ls-remote -q origin in /var/folders/26/gqnv01_55p964v8yz39d51fw0000gn/T/hugo_cache/modules/filecache/modules/pkg/mod/cache/vcs/b410fc7b91fbc1121b5f6ec2bb2711c27cd172b4084c213e1430a33cde552597: exit status 128:
remote: Repository not found.
fatal: repository 'https://github.com/USER/REPOSITORY/' not found
How can I get Go/Hugo to use my local git config rather than the global?
From the hugo mod source code, hugo will look for a go.mod in your project:
filepath.Walk(dirname, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
if info.Name() == "go.mod" {
// Found a module.
dir := filepath.Dir(path)
fmt.Println("Update module in", dir)
Check where your go.mod is, and do (in that go.mod parent folder):
git config -l --show-origin --show-scope
That will tell you if your expected local config is actually there or not.
Look for any .git folder which would indicate a nested git repository/submodule, which would ignore your initial git config --local command
An issue like 34513 seems to suggests though that go mod won't take into account the local repository:
The git configuration only affects operations on the underlying git repo.
The error that you're seeing is coming from before that, when the go command is attempting to resolve the repo for the requested package path.
The official documentation only references the global config .gitconfig.
I solved this by adding a directory replacement mapping to the site’s config, instead of modifying the git url. This points to my locally cloned theme and updates the served site whenever I modify the theme.
module:
imports:
path: 'github.com/[USER]/[REPO-NAME]'
replacements: 'github.com/[USER]/[REPO-NAME] -> ../../[REPO-NAME]/'

Go get is pulling the wrong repository

My module is gitlab.com/getsote/utilities/slogger
My repository is gitlab.com/getsote/utilities/slogger.git
When I run go get gitlab.com/getsote/utilities/slogger, I get the message below.
Scotts-Mac-mini:seeding syacko$ go get gitlab.com/getsote/utilities/slogger
go get gitlab.com/getsote/utilities/slogger: module gitlab.com/getsote/utilities/slogger: git ls-remote -q origin in /Users/syacko/workspace/sotesoft/golang/pkg/mod/cache/vcs/80b3644beae1b986f1c659355360479e2463820660aa328d2edb1e571aba259b: exit status 128:
remote: The project you were looking for could not be found.
fatal: repository 'https://gitlab.com/getsote/utilities.git/' not found
Scotts-Mac-mini:seeding syacko$
The gitlab.com/getsote/utilities.git is a sub-directory and not a repository. I don't understand why go get is going to the utilities as a repository?
==========================
PREVIOUS Updates
Directory Structure:
GOPATH/src/slogger
|----go.mod
|----slogger.go
|----slogger_test.go
go.mod file
module slogger or gitlab.com/getsote/utilities/slogger -> still gets the error below
go 1.14
gitlab.com/getsote/utilities contains repository slogger.git
I have run a test to see if the issue is the number of nodes in the path. So, I create a new repository with no sub-directory and pushed the slogger code. Then ran go get gitlab.com/getsote/slogger which generate a different error message.
GOPATH/gitlab.com/getsote/test-go-mod -> create new directory and added slogger files listed above
gitblab.com/getsote/test-go-mod -> new repository with one less level
Scotts-Mac-mini:test-go-mod syacko$ go get gitlab.com/getsote/test-go-mod
go: downloading gitlab.com/getsote/test-go-mod v0.0.0-20200409023538-794310bf7cf9
go get gitlab.com/getsote/test-go-mod: gitlab.com/getsote/test-go-mod#v0.0.0-20200409023538-794310bf7cf9: verifying module: gitlab.com/getsote/test-go-mod#v0.0.0-20200409023538-794310bf7cf9: reading https://sum.golang.org/lookup/gitlab.com/getsote/test-go-mod#v0.0.0-20200409023538-794310bf7cf9: 410 Gone
server response:
not found: gitlab.com/getsote/test-go-mod#v0.0.0-20200409023538-794310bf7cf9: invalid version: git fetch -f origin refs/heads/*:refs/heads/* refs/tags/*:refs/tags/* in /tmp/gopath/pkg/mod/cache/vcs/7753c92c9bd1419156d8120684b7f3707fd207e01a2947ba89e2acfd2ecfb4d0: exit status 128:
fatal: could not read Username for 'https://gitlab.com': terminal prompts disabled
Scotts-Mac-mini:test-go-mod syacko$
This is still getting the status error of 128 for the missing version. Additionally, it is looking in the right location for the code. If this is true, then I just need help with the version missing. Moving to a shorted directory structure is doable.
========================
Newest Update
#praveent > The solution at https://medium.com/cloud-native-the-gathering/go-modules-with-private-git-repositories-dfe795068db4 didn't work for me. So I started from scratch to see how to resolve the issue.
The reason is because for a git repository it assumes that utilities is the repo and not utilities/slogger
There is a way to override this behavior by implementing go get API. But, gitlab is yet to implement the same due to security concerns. You can read more here. Gitlab issue
Update: Add reference to gitlab issue tracking this problem.
So, here is how I got this to work using gitlab.com. I'm not saying other ways will not work, they just didn't for me and my setup. First, since I don't care if the code is available to the public, I created a new group at gitlab.com. This new group is public from the start, so no need to adjust permissions. Then I create a repository called packages and cloned the repository to my local machine with the same directory structure that is in gitlab.com, gitlab.com/soteapps/packages with ~/workspace/soteapps/packages on my machine. Both of these are out side the GOPATH. I'm not sure this matters, but it is working this way, so I'm putting it here.
Under packages, I copied the slogger directory and code.
cp -R slogger ~/workspace/soteapps/packages/.
Edited the go.mod file to match the repository structure, which is in the packages directory. There is no go.mod file in the slogger directory.
module gitlab.com/soteapps/packages
go 1.14
Edited the hello.go import to match the package.
package main
import (
"fmt"
"rsc.io/quote"
"gitlab.com/soteapps/packages/slogger"
)
func main() {
fmt.Println(quote.Hello())
slogger.Info("Test message")
}
Built the program using go build -o hello and then ran it hello with the following results:
Scotts-Mac-mini:hello syacko$ hello
Hello, world.
INFO:2020/04/10 21:11:33 Test message
Scotts-Mac-mini:hello syacko$
Worked! Thank you all that helped. This wouldn't of gotten solved without your help.
Note: This only works for public repositories.

Using forked package import in Go

Suppose you have a repository at github.com/someone/repo and you fork it to github.com/you/repo. You want to use your fork instead of the main repo, so you do a
go get github.com/you/repo
Now all the import paths in this repo will be "broken", meaning, if there are multiple packages in the repository that reference each other via absolute URLs, they will reference the source, not the fork.
Is there a better way as cloning it manually into the right path?
git clone git#github.com:you/repo.git $GOPATH/src/github.com/someone/repo
If you are using go modules. You could use replace directive
The replace directive allows you to supply another import path that might
be another module located in VCS (GitHub or elsewhere), or on your
local filesystem with a relative or absolute file path. The new import
path from the replace directive is used without needing to update the
import paths in the actual source code.
So you could do below in your go.mod file
module some-project
go 1.12
require (
github.com/someone/repo v1.20.0
)
replace github.com/someone/repo => github.com/you/repo v3.2.1
where v3.2.1 is tag on your repo. Also can be done through CLI
go mod edit -replace="github.com/someone/repo#v0.0.0=github.com/you/repo#v1.1.1"
To handle pull requests
fork a repository github.com/someone/repo to github.com/you/repo
download original code: go get github.com/someone/repo
be there: cd "$(go env GOPATH)/src"/github.com/someone/repo
enable uploading to your fork: git remote add myfork https://github.com/you/repo.git
upload your changes to your repo: git push myfork
http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html
To use a package in your project
https://github.com/golang/go/wiki/PackageManagementTools
One way to solve it is that suggested by Ivan Rave and http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html -- the way of forking.
Another one is to workaround the golang behavior. When you go get, golang lays out your directories under same name as in the repository URI, and this is where the trouble begins.
If, instead, you issue your own git clone, you can clone your repository onto your filesystem on a path named after the original repository.
Assuming original repository is in github.com/awsome-org/tool and you fork it onto github.com/awesome-you/tool, you can:
cd $GOPATH
mkdir -p {src,bin,pkg}
mkdir -p src/github.com/awesome-org/
cd src/github.com/awesome-org/
git clone git#github.com:awesome-you/tool.git # OR: git clone https://github.com/awesome-you/tool.git
cd tool/
go get ./...
golang is perfectly happy to continue with this repository and doesn't actually care some upper directory has the name awesome-org while the git remote is awesome-you. All import for awesome-org are resovled via the directory you have just created, which is your local working set.
In more length, please see my blog post: Forking Golang repositories on GitHub and managing the import path
edit: fixed directory path
If your fork is only temporary (ie you intend that it be merged) then just do your development in situ, eg in $GOPATH/src/launchpad.net/goamz.
You then use the features of the version control system (eg git remote) to make the upstream repository your repository rather than the original one.
It makes it harder for other people to use your repository with go get but much easier for it to be integrated upstream.
In fact I have a repository for goamz at lp:~nick-craig-wood/goamz/goamz which I develop for in exactly that way. Maybe the author will merge it one day!
Here's a way to that works for everyone:
Use github to fork to "my/repo" (just an example):
go get github.com/my/repo
cd ~/go/src/github.com/my/repo
git branch enhancement
rm -rf .
go get github.com/golang/tools/cmd/gomvpkg/…
gomvpkg <<oldrepo>> ~/go/src/github.com/my/repo
git commit
Repeat each time when you make the code better:
git commit
git checkout enhancement
git cherry-pick <<commit_id>>
git checkout master
Why? This lets you have your repo that any go get works with. It also lets you maintain & enhance a branch that's good for a pull request. It doesn't bloat git with "vendor", it preserves history, and build tools can make sense of it.
Instead of cloning to a specific location, you can clone wherever you want.
Then, you can run a command like this, to have Go refer to the local version:
go mod edit -replace github.com/owner/repo=../repo
https://golang.org/cmd/go#hdr-Module_maintenance
The answer to this is that if you fork a repo with multiple packages you will need to rename all the relevant import paths. This is largely a good thing since you've forked all of those packages and the import paths should reflect this.
Use vendoring and submodules together
Fork the lib on github (go-mssqldb in this case)
Add a submodule which clones your fork into your vendor folder but has the path of the upstream repo
Update your import statements in your source code to point to the vendor folder, (not including the vendor/ prefix). E.g. vendor/bob/lib => import "bob/lib"
E.g.
cd ~/go/src/github.com/myproj
mygithubuser=timabell
upstreamgithubuser=denisenkom
librepo=go-mssqldb
git submodule add "git#github.com:$mygithubuser/$librepo" "vendor/$upstreamgithubuser/$librepo"
Why
This solves all the problems I've heard about and come across while trying to figure this out myself.
Internal package refs in the lib now work because the path is unchanged from upstream
A fresh checkout of your project works because the submodule system gets it from your fork at the right commit but in the upstream folder path
You don't have to know to manually hack the paths or mess with the go tooling.
More info
https://git-scm.com/book/en/v2/Git-Tools-Submodules
How do I fix the error message "use of an internal package not allowed" when go getting a golang package?
https://github.com/denisenkom/go-mssqldb/issues/406
https://github.com/golang/go/wiki/PackageManagementTools#go15vendorexperiment
The modern answer (go 1.15 and higher, at least).
go mod init github.com/theirs/repo
Make an explicit init arg that is the ORIGINAL package names. If you don't include the repo name, it will assume the one in gopath. But when you use go modules, they no longer care where they are on disk, or where git actually pulls dependencies from.
To automate this process, I wrote a small script. You can find more details on my blog to add a command like "gofork" to your bash.
function gofork() {
if [ $# -ne 2 ] || [ -z "$1" ] || [ -z "$2" ]; then
echo 'Usage: gofork yourFork originalModule'
echo 'Example: gofork github.com/YourName/go-contrib github.com/heirko/go-contrib'
return
fi
echo "Go get fork $1 and replace $2 in GOPATH: $GOPATH"
go get $1
go get $2
currentDir=$PWD
cd $GOPATH/src/$1
remote1=$(git config --get remote.origin.url)
cd $GOPATH/src/$2
remote2=$(git config --get remote.origin.url)
cd $currentDir
rm -rf $GOPATH/src/$2
mv $GOPATH/src/$1 $GOPATH/src/$2
cd $GOPATH/src/$2
git remote add their $remote2
echo Now in $GOPATH/src/$2 origin remote is $remote1
echo And in $GOPATH/src/$2 their remote is $remote2
cd $currentDir
}
export -f gofork
You can use command go get -f to get you a forked repo
in your Gopkg.toml file add these block below
[[constraint]]
name = "github.com/globalsign/mgo"
branch = "master"
source = "github.com/myfork/project2"
So it will use the forked project2 in place of github.com/globalsign/mgo

Update Local Workspace to SVN Repository 'Head' With Ruby SVN Bindings

I am writing a program in Ruby that necessitates downloading the most current version of my team's software from SVN upon start up.
The checkout function (from the Ruby SVN bindings) is what I believe I want to use, because an update would not ADD any files that do not exist on my machine's local "trunk" workspace. A checkout statement would both update files that do not match to HEAD, and it would download ones that don't exist at all. Effectively, after running a fully recursive checkout, I would hope to have an exact copy of the most recent SVN repository.
According to this API, a checkout statement basically takes the following:
an exact SVN URL
a local root project directory
a revision (I would be using the string 'HEAD')
recursive (integer 1 or 0)
a pool object (I cannot determine what this is for exactly, but I don't think it affects me)
Here's what I wrote, inside a block that iterates for each file in the SVN repository:
if status != NORMAL #any file that changed or is 'missing'
ctx.checkout(status.entry.url, ROOTDIR, 'HEAD', 0, nil) #update abnormal file to HEAD
end
As a test, I erased a directory from my local workspace, and attempted to restore it with this command. It runs through until it reaches one of the missing files, at which point it raises an error:
`svn_client_checkout3': subversion/libsvn_fs_fs/tree.c:663: Svn::Error::FsNotFound: File not found: revision 0, path '/trunk/project-gadfly/SocketServer/DiscoveryServer.cpp' (Svn::Error::FsNotFound)
I do not understand why this error would be raised, because I thought that a checkout statement would see that the directory (i.e. file) does not exist locally and then create it. Perhaps I am doing something wrong?
Looking back on what I've written, I think all of this was a long-winded way of asking the following simple question: How do I get the most current version of SVN repository onto my local hard drive with an SVN Ruby command?
Thanks in advance,
Elwood Hopkins
I don't know about Ruby-specific part of the question, but it's clear that you asked SVN API to checkout "status.entry.url" at revision 0, which of course doesn't exist here.
It's also strange that you looked into Perl documentation for writing in Ruby. I would recommend you to look at Subversion sources instead.
Here's Ruby method declaration:
http://svn.apache.org/repos/asf/subversion/branches/1.7.x/subversion/bindings/swig/ruby/svn/client.rb
def checkout(url, path, revision=nil, peg_rev=nil,
depth=nil, ignore_externals=false,
allow_unver_obstruction=false)
revision ||= "HEAD"
Client.checkout3(url, path, peg_rev, revision, depth,
ignore_externals, allow_unver_obstruction,
self)
end
So as you can see, you've specified 0 as peg revision. But you should specify HEAD instead.
What about pools --- they are parts of SVN memory managements. Here's the explanation: http://subversion.apache.org/docs/community-guide/conventions.html#apr-pools

Resources