Skip to content

Commit 994705a

Browse files
authored
Merge pull request #2637 from dnenov/git-install-privte-fix
LibGit2Sharp missing CredentialsProvider fix
2 parents 33d8118 + 246328c commit 994705a

File tree

1 file changed

+109
-80
lines changed
  • pyrevitlib/pyrevit/coreutils

1 file changed

+109
-80
lines changed

pyrevitlib/pyrevit/coreutils/git.py

Lines changed: 109 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,46 @@
44
https://github.com/libgit2/libgit2sharp/wiki
55
"""
66

7-
import importlib
87
import os.path as op
98
from collections import OrderedDict
109

1110
from pyrevit import HOST_APP, PyRevitException
12-
import pyrevit.compat as compat
1311
from pyrevit.compat import PY3, safe_strtype
1412
from pyrevit import framework
1513
from pyrevit.framework import clr
1614
from pyrevit.framework import DateTime, DateTimeOffset
1715
from pyrevit.coreutils.logger import get_logger
1816

19-
#pylint: disable=W0703,C0302
20-
mlogger = get_logger(__name__) #pylint: disable=C0103
17+
# pylint: disable=W0703,C0302
18+
mlogger = get_logger(__name__) # pylint: disable=C0103
2119

2220

23-
GIT_LIB = 'LibGit2Sharp'
21+
GIT_LIB = "LibGit2Sharp"
2422

2523
LIBGIT_DLL = framework.get_dll_file(GIT_LIB)
26-
mlogger.debug('Loading dll: %s', LIBGIT_DLL)
24+
mlogger.debug("Loading dll: %s", LIBGIT_DLL)
2725

2826
try:
2927
if PY3:
3028
clr.AddReference(LIBGIT_DLL)
3129
else:
3230
clr.AddReferenceToFileAndPath(LIBGIT_DLL)
3331

34-
import LibGit2Sharp as libgit #pylint: disable=import-error
32+
import LibGit2Sharp as libgit # pylint: disable=import-error
3533

3634
except Exception as load_err:
37-
mlogger.error('Can not load %s module. '
38-
'This module is necessary for getting pyRevit version '
39-
'and staying updated. | %s', GIT_LIB, load_err)
35+
mlogger.error(
36+
"Can not load %s module. "
37+
"This module is necessary for getting pyRevit version "
38+
"and staying updated. | %s",
39+
GIT_LIB,
40+
load_err,
41+
)
4042

4143

4244
class PyRevitGitAuthenticationError(PyRevitException):
4345
"""Git authentication error."""
46+
4447
pass
4548

4649

@@ -57,6 +60,7 @@ class RepoInfo(object):
5760
username (str): credentials - username
5861
password (str): credentials - password
5962
"""
63+
6064
def __init__(self, repo):
6165
self.directory = repo.Info.WorkingDirectory
6266
self.name = op.basename(op.normpath(self.directory))
@@ -67,8 +71,9 @@ def __init__(self, repo):
6771
self.username = self.password = None
6872

6973
def __repr__(self):
70-
return '<type \'RepoInfo\' head \'{}\' @ {}>'\
71-
.format(self.last_commit_hash, self.directory)
74+
return "<type 'RepoInfo' head '{}' @ {}>".format(
75+
self.last_commit_hash, self.directory
76+
)
7277

7378

7479
def _credentials_hndlr(username, password):
@@ -79,64 +84,81 @@ def _credentials_hndlr(username, password):
7984

8085

8186
def _get_credentials_hndlr(username, password):
82-
return libgit.Handlers. \
83-
CredentialsHandler(lambda url, uname, types:
84-
_credentials_hndlr(username, password))
87+
return libgit.Handlers.CredentialsHandler(
88+
lambda url, uname, types: _credentials_hndlr(username, password)
89+
)
8590

8691

8792
def _make_pull_options(repo_info):
88-
mlogger.debug('Making pull options: %s', repo_info)
93+
mlogger.debug("Making pull options: %s", repo_info)
8994
pull_ops = libgit.PullOptions()
9095
pull_ops.FetchOptions = libgit.FetchOptions()
9196
if repo_info.username and repo_info.password:
92-
mlogger.debug('Making Credentials handler. '
93-
'(Username and password are available but'
94-
'will not be logged for privacy purposes.)')
97+
mlogger.debug(
98+
"Making Credentials handler. "
99+
"(Username and password are available but"
100+
"will not be logged for privacy purposes.)"
101+
)
95102

96-
pull_ops.FetchOptions.CredentialsProvider = \
97-
_get_credentials_hndlr(repo_info.username, repo_info.password)
103+
pull_ops.FetchOptions.CredentialsProvider = _get_credentials_hndlr(
104+
repo_info.username, repo_info.password
105+
)
98106

99107
return pull_ops
100108

101109

102110
def _make_fetch_options(repo_info):
103-
mlogger.debug('Making fetch options: %s', repo_info)
111+
mlogger.debug("Making fetch options: %s", repo_info)
104112
fetch_ops = libgit.FetchOptions()
105113
if repo_info.username and repo_info.password:
106-
mlogger.debug('Making Credentials handler. '
107-
'(Username and password are available but'
108-
'will not be logged for privacy purposes.)')
114+
mlogger.debug(
115+
"Making Credentials handler. "
116+
"(Username and password are available but"
117+
"will not be logged for privacy purposes.)"
118+
)
109119

110-
fetch_ops.CredentialsProvider = \
111-
_get_credentials_hndlr(repo_info.username, repo_info.password)
120+
fetch_ops.CredentialsProvider = _get_credentials_hndlr(
121+
repo_info.username, repo_info.password
122+
)
112123

113124
return fetch_ops
114125

115126

116127
def _make_clone_options(username=None, password=None):
117-
mlogger.debug('Making clone options.')
128+
mlogger.debug("Making clone options.")
118129
clone_ops = libgit.CloneOptions()
119-
if username and password:
120-
mlogger.debug('Making Credentials handler. '
121-
'(Username and password are available but'
122-
'will not be logged for privacy purposes.)')
123130

124-
clone_ops.CredentialsProvider = \
125-
_get_credentials_hndlr(username, password)
131+
if username and password:
132+
mlogger.debug("Making Credentials handler.")
133+
creds_handler = _get_credentials_hndlr(username, password)
134+
135+
# Only set the CredentialsProvider if it's a valid property
136+
if hasattr(clone_ops, "CredentialsProvider"):
137+
clone_ops.CredentialsProvider = creds_handler
138+
elif hasattr(clone_ops, "FetchOptions") and hasattr(
139+
clone_ops.FetchOptions, "CredentialsProvider"
140+
):
141+
clone_ops.FetchOptions.CredentialsProvider = creds_handler
142+
else:
143+
mlogger.warning(
144+
"CloneOptions does not support CredentialsProvider. "
145+
"Skipping credentials."
146+
)
126147

127148
return clone_ops
128149

129150

130151
def _make_pull_signature():
131-
mlogger.debug('Creating pull signature for username: %s', HOST_APP.username)
132-
return libgit.Signature(HOST_APP.username,
133-
HOST_APP.username,
134-
DateTimeOffset(DateTime.Now))
152+
mlogger.debug("Creating pull signature for username: %s",
153+
HOST_APP.username)
154+
return libgit.Signature(
155+
HOST_APP.username, HOST_APP.username, DateTimeOffset(DateTime.Now)
156+
)
135157

136158

137159
def _process_git_error(exception_err):
138160
exception_msg = safe_strtype(exception_err)
139-
if '401' in exception_msg:
161+
if "401" in exception_msg:
140162
raise PyRevitGitAuthenticationError(exception_msg)
141163
else:
142164
raise PyRevitException(exception_msg)
@@ -166,18 +188,19 @@ def git_pull(repo_info):
166188
"""
167189
repo = repo_info.repo
168190
try:
169-
libgit.Commands.Pull(repo,
170-
_make_pull_signature(),
171-
_make_pull_options(repo_info))
191+
libgit.Commands.Pull(
192+
repo, _make_pull_signature(), _make_pull_options(repo_info)
193+
)
172194

173-
mlogger.debug('Successfully pulled repo: %s', repo_info.directory)
174-
head_msg = safe_strtype(repo.Head.Tip.Message).replace('\n', '')
195+
mlogger.debug("Successfully pulled repo: %s", repo_info.directory)
196+
head_msg = safe_strtype(repo.Head.Tip.Message).replace("\n", "")
175197

176-
mlogger.debug('New head is: %s > %s', repo.Head.Tip.Id.Sha, head_msg)
198+
mlogger.debug("New head is: %s > %s", repo.Head.Tip.Id.Sha, head_msg)
177199
return RepoInfo(repo)
178200

179201
except Exception as pull_err:
180-
mlogger.debug('Failed git pull: %s | %s', repo_info.directory, pull_err)
202+
mlogger.debug("Failed git pull: %s | %s",
203+
repo_info.directory, pull_err)
181204
_process_git_error(pull_err)
182205

183206

@@ -192,20 +215,22 @@ def git_fetch(repo_info):
192215
"""
193216
repo = repo_info.repo
194217
try:
195-
libgit.Commands.Fetch(repo,
196-
repo.Head.TrackedBranch.RemoteName,
197-
[],
198-
_make_fetch_options(repo_info),
199-
'fetching pyrevit updates')
200-
201-
mlogger.debug('Successfully pulled repo: %s', repo_info.directory)
202-
head_msg = safe_strtype(repo.Head.Tip.Message).replace('\n', '')
203-
204-
mlogger.debug('New head is: %s > %s', repo.Head.Tip.Id.Sha, head_msg)
218+
libgit.Commands.Fetch(
219+
repo,
220+
repo.Head.TrackedBranch.RemoteName,
221+
[],
222+
_make_fetch_options(repo_info),
223+
"fetching pyrevit updates",
224+
)
225+
226+
mlogger.debug("Successfully pulled repo: %s", repo_info.directory)
227+
head_msg = safe_strtype(repo.Head.Tip.Message).replace("\n", "")
228+
229+
mlogger.debug("New head is: %s > %s", repo.Head.Tip.Id.Sha, head_msg)
205230
return RepoInfo(repo)
206231

207232
except Exception as fetch_err:
208-
mlogger.debug('Failed git fetch: %s | %s',
233+
mlogger.debug("Failed git fetch: %s | %s",
209234
repo_info.directory, fetch_err)
210235
_process_git_error(fetch_err)
211236

@@ -220,16 +245,18 @@ def git_clone(repo_url, clone_dir, username=None, password=None):
220245
password (str): credentials - password
221246
"""
222247
try:
223-
libgit.Repository.Clone(repo_url,
224-
clone_dir,
225-
_make_clone_options(username=username,
226-
password=password))
248+
libgit.Repository.Clone(
249+
repo_url,
250+
clone_dir,
251+
_make_clone_options(username=username, password=password),
252+
)
227253

228-
mlogger.debug('Completed git clone: %s @ %s', repo_url, clone_dir)
254+
mlogger.debug("Completed git clone: %s @ %s", repo_url, clone_dir)
229255

230256
except Exception as clone_err:
231-
mlogger.debug('Error cloning repo: %s to %s | %s',
232-
repo_url, clone_dir, clone_err)
257+
mlogger.debug(
258+
"Error cloning repo: %s to %s | %s", repo_url, clone_dir, clone_err
259+
)
233260
_process_git_error(clone_err)
234261

235262

@@ -243,28 +270,31 @@ def compare_branch_heads(repo_info):
243270
repo = repo_info.repo
244271
repo_branches = repo.Branches
245272

246-
mlogger.debug('Repo branches: %s', [b.FriendlyName for b in repo_branches])
273+
mlogger.debug("Repo branches: %s", [b.FriendlyName for b in repo_branches])
247274

248275
for branch in repo_branches:
249276
if branch.FriendlyName == repo_info.branch and not branch.IsRemote:
250277
try:
251278
if branch.TrackedBranch:
252-
mlogger.debug('Comparing heads: %s of %s',
253-
branch.CanonicalName,
254-
branch.TrackedBranch.CanonicalName)
255-
256-
hist_div = repo.ObjectDatabase. \
257-
CalculateHistoryDivergence(branch.Tip,
258-
branch.TrackedBranch.Tip)
279+
mlogger.debug(
280+
"Comparing heads: %s of %s",
281+
branch.CanonicalName,
282+
branch.TrackedBranch.CanonicalName,
283+
)
284+
285+
hist_div = repo.ObjectDatabase.CalculateHistoryDivergence(
286+
branch.Tip, branch.TrackedBranch.Tip
287+
)
259288
return hist_div
260289
except Exception as compare_err:
261-
mlogger.error('Can not compare branch %s in repo: %s | %s',
262-
branch,
263-
repo,
264-
safe_strtype(compare_err).replace('\n', ''))
290+
mlogger.error(
291+
"Can not compare branch %s in repo: %s | %s",
292+
branch,
293+
repo,
294+
safe_strtype(compare_err).replace("\n", ""),
295+
)
265296
else:
266-
mlogger.debug('Skipping remote branch: %s', branch.CanonicalName)
267-
297+
mlogger.debug("Skipping remote branch: %s", branch.CanonicalName)
268298

269299

270300
def get_all_new_commits(repo_info):
@@ -294,8 +324,7 @@ def get_all_new_commits(repo_info):
294324
commits = repo.Commits.QueryBy(commit_filter)
295325
commitsdict = OrderedDict()
296326
for commit in commits:
297-
if commit in repo.Head.Commits \
298-
or commit in repo.Head.TrackedBranch.Commits:
327+
if commit in repo.Head.Commits or commit in repo.Head.TrackedBranch.Commits:
299328
commitsdict[commit.Id.ToString()] = commit.MessageShort
300329

301330
return commitsdict

0 commit comments

Comments
 (0)