Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
G
GPM - NTNU Git Profile Manager
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Leo
GPM - NTNU Git Profile Manager
Commits
f9750937
Commit
f9750937
authored
11 months ago
by
Leo
Browse files
Options
Downloads
Patches
Plain Diff
chore(comments): Add better docs
parent
5bd42058
No related branches found
No related tags found
No related merge requests found
Pipeline
#291438
passed
11 months ago
Stage: build
Stage: deploy
Changes
2
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
.idea/workspace.xml
+3
-2
3 additions, 2 deletions
.idea/workspace.xml
gpm/cli.py
+122
-4
122 additions, 4 deletions
gpm/cli.py
with
125 additions
and
6 deletions
.idea/workspace.xml
+
3
−
2
View file @
f9750937
...
...
@@ -5,7 +5,8 @@
</component>
<component
name=
"ChangeListManager"
>
<list
default=
"true"
id=
"2f47370d-26d1-4fc6-a93f-363c8b4c6e5a"
name=
"Changes"
comment=
""
>
<change
beforePath=
"$PROJECT_DIR$/.gitlab-ci.yml"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/.gitlab-ci.yml"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/.idea/workspace.xml"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/.idea/workspace.xml"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/gpm/cli.py"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/gpm/cli.py"
afterDir=
"false"
/>
</list>
<option
name=
"SHOW_DIALOG"
value=
"false"
/>
<option
name=
"HIGHLIGHT_CONFLICTS"
value=
"true"
/>
...
...
@@ -83,7 +84,7 @@
<option
name=
"presentableId"
value=
"Default"
/>
<updated>
1724140762915
</updated>
<workItem
from=
"1724140765116"
duration=
"10726000"
/>
<workItem
from=
"1724224393281"
duration=
"8
004
000"
/>
<workItem
from=
"1724224393281"
duration=
"8
838
000"
/>
</task>
<servers
/>
</component>
...
...
This diff is collapsed.
Click to expand it.
gpm/cli.py
+
122
−
4
View file @
f9750937
...
...
@@ -53,6 +53,10 @@ def find_best_match(query, options):
def
setup
():
"""
Setup the CLI parser, handle argument- and subcommand parsing.
:return:
"""
if
not
os
.
path
.
exists
(
data_location
):
os
.
makedirs
(
data_location
)
if
not
os
.
path
.
exists
(
data_file
):
...
...
@@ -121,6 +125,10 @@ def setup():
@dataclass
class
Profile
:
"""
Dataclass for a git profile.
Represents a git profile with a name, email and optional comment.
"""
name
:
str
email
:
str
comment
:
Optional
[
str
]
=
None
...
...
@@ -135,12 +143,23 @@ class Profile:
class
GPM
:
"""
Git Profile Manager class. Otherwise known as the Main Program
"""
def
__init__
(
self
,
use_global_git_config
=
False
):
"""
Initialize the Git Profile Manager
:param use_global_git_config: Whether to use the global git config or not, when initializing the class
"""
self
.
profiles
=
[]
self
.
_load
()
self
.
_load
()
# Load profiles from file `data_file`
self
.
use_global_git_config
=
use_global_git_config
def
_load
(
self
):
"""
Load profiles from the data file
:return: List of profiles
"""
with
open
(
data_file
,
"
r
"
)
as
f
:
data
=
json
.
load
(
f
)
try
:
...
...
@@ -149,11 +168,22 @@ class GPM:
print
(
f
"
{
colorama
.
Fore
.
RED
}
Error loading profiles
{
colorama
.
Style
.
RESET_ALL
}
"
)
sys
.
exit
(
1
)
def
_save
(
self
):
def
_save
(
self
)
->
None
:
"""
Save the profiles to the data file
:return: None
"""
with
open
(
data_file
,
"
w
"
)
as
f
:
json
.
dump
([
profile
.
__dict__
for
profile
in
self
.
profiles
],
f
,
indent
=
4
)
def
add
(
self
,
name
,
email
,
comment
=
None
):
"""
Add a new profile to the list of profiles
:param name: The name of the profile
:param email: The email of the profile
:param comment: Optional comment for the profile
:return: None
"""
# Validate name and email
if
not
re
.
match
(
r
"
[^@]+@[^@]+\.[^@]+
"
,
email
):
print
(
f
"
{
colorama
.
Fore
.
RED
}
Invalid email
{
colorama
.
Style
.
RESET_ALL
}
:
{
email
}
"
)
...
...
@@ -161,6 +191,8 @@ class GPM:
if
not
name
:
print
(
f
"
{
colorama
.
Fore
.
RED
}
Name cannot be empty
{
colorama
.
Style
.
RESET_ALL
}
"
)
return
# Check if profile already exists
for
profile
in
self
.
profiles
:
if
profile
.
email
==
email
:
print
(
f
"
{
colorama
.
Fore
.
RED
}
Email
{
email
}
already exists
{
colorama
.
Style
.
RESET_ALL
}
"
)
...
...
@@ -168,10 +200,17 @@ class GPM:
profile
=
Profile
(
name
,
email
,
comment
)
self
.
profiles
.
append
(
profile
)
self
.
_save
()
#print(f"Added profile: {name} <{email}>")
print
(
f
"
{
colorama
.
Fore
.
GREEN
}
Added profile:
{
self
.
get_profile_format
(
profile
)
}
"
)
def
edit
(
self
,
query
,
name
=
None
,
email
=
None
,
comment
=
None
):
"""
Edit an existing profile
:param query: The query to match the profile to edit
:param name: If provided, the new name for the profile
:param email: If provided, the new email for the profile
:param comment: If provided, the new comment for the profile
:return:
"""
if
not
name
and
not
email
and
not
comment
:
print
(
f
"
{
colorama
.
Fore
.
RED
}
Nothing to edit
{
colorama
.
Style
.
RESET_ALL
}
"
)
return
...
...
@@ -188,6 +227,10 @@ class GPM:
print
(
f
"
{
colorama
.
Fore
.
GREEN
}
Edited profile:
{
self
.
get_profile_format
(
profile
)
}{
colorama
.
Style
.
RESET_ALL
}
"
)
def
list
(
self
):
"""
List all profiles
:return: None
"""
if
not
self
.
profiles
:
print
(
f
"
{
colorama
.
Fore
.
YELLOW
}
No profiles found
{
colorama
.
Style
.
RESET_ALL
}
"
)
else
:
...
...
@@ -195,7 +238,12 @@ class GPM:
print
(
f
"
{
index
}
.
{
profile
}
"
)
def
match_query_to_profile
(
self
,
query
:
str
):
def
match_query_to_profile
(
self
,
query
:
str
)
->
Optional
[
Profile
]:
"""
Match a query to a profile
:param query: The query to match
:return: The profile if found, otherwise None
"""
if
query
.
isdigit
():
index
=
int
(
query
)
-
1
if
index
<
0
or
index
>=
len
(
self
.
profiles
):
...
...
@@ -222,15 +270,30 @@ class GPM:
return
profile
def
get_profile_format
(
self
,
profile
:
Profile
):
"""
Get the formatted profile string
:param profile:
:return: The formatted profile string in format (index) name (comment) <email>
"""
return
f
"
(
{
self
.
get_profile_number
(
profile
)
}
)
{
profile
}
"
def
_get_git_subcommand
(
self
,
*
params
):
"""
Get the git subcommand for a given set of parameters
:param params: The parameters to pass to the git command
:return: The git command string
"""
git_command
=
"
git config
"
if
self
.
use_global_git_config
:
git_command
+=
"
--global
"
return
f
"
{
git_command
}
{
'
'
.
join
(
params
)
}
"
def
use
(
self
,
name_or_email
):
"""
Use a profile, by applying the name and email to the git config
:param name_or_email: The name or email of the profile to use
:return: None
"""
if
profile
:
=
self
.
match_query_to_profile
(
name_or_email
):
print
(
f
"
Using profile
{
self
.
get_profile_format
(
profile
)
}
"
,
end
=
"
"
)
try
:
...
...
@@ -243,6 +306,11 @@ class GPM:
print
(
f
"
{
colorama
.
Fore
.
RED
}
No matching profile found for
'
{
name_or_email
}
'
{
colorama
.
Style
.
RESET_ALL
}
"
)
def
remove
(
self
,
name
):
"""
Remove a profile
:param name: The name or email of the profile to remove
:return: None
"""
if
profile
:
=
self
.
match_query_to_profile
(
name
):
out_text
=
f
"
{
colorama
.
Fore
.
GREEN
}
Removed profile:
{
self
.
get_profile_format
(
profile
)
}{
colorama
.
Style
.
RESET_ALL
}
"
self
.
profiles
.
remove
(
profile
)
...
...
@@ -252,6 +320,10 @@ class GPM:
print
(
f
"
{
colorama
.
Fore
.
RED
}
No matching profile found for
'
{
name
}
'
{
colorama
.
Style
.
RESET_ALL
}
"
)
def
load_git_profile
(
self
)
->
Optional
[
Profile
]:
"""
Load the git profile from the git config
:return: The git profile
"""
name
=
os
.
popen
(
self
.
_get_git_subcommand
(
"
user.name
"
)).
read
().
strip
()
email
=
os
.
popen
(
self
.
_get_git_subcommand
(
"
user.email
"
)).
read
().
strip
()
try
:
...
...
@@ -261,6 +333,10 @@ class GPM:
return
Profile
(
name
or
""
,
email
or
""
)
def
_get_local_profile_or_create
(
self
)
->
Optional
[
Profile
]:
"""
Get the local profile or create a new one
:return: The local profile
"""
profile
=
self
.
load_git_profile
()
if
not
profile
:
print
(
f
"
{
colorama
.
Fore
.
YELLOW
}
No current profile set
{
colorama
.
Style
.
RESET_ALL
}
"
)
...
...
@@ -280,6 +356,10 @@ class GPM:
return
profile
def
current_show
(
self
):
"""
Show the current profile
:return: None
"""
profile
=
self
.
_get_local_profile_or_create
()
if
not
profile
:
return
...
...
@@ -294,12 +374,24 @@ class GPM:
sys
.
exit
(
1
)
def
get_profile_number
(
self
,
profile
:
Profile
)
->
int
:
"""
Returns the profile number for a given profile if it exists, otherwise -1
:param profile:
:return: The profile number for a given profile if it exists, otherwise -1
"""
for
index
,
prf
in
enumerate
(
self
.
profiles
,
start
=
1
):
if
prf
.
email
==
profile
.
email
:
return
index
return
-
1
def
current_edit
(
self
,
name
=
None
,
email
=
None
,
comment
=
None
):
"""
Edit the current profile
:param name: If provided, the new name for the profile
:param email: If provided, the new email for the profile
:param comment: If provided, the new comment for the profile
:return: None
"""
local_profile
=
self
.
_get_local_profile_or_create
()
self
.
_validate_name_email
(
local_profile
.
email
,
local_profile
.
name
)
profile
=
self
.
_validate_query_profile_or_exit
(
local_profile
.
email
)
...
...
@@ -314,11 +406,21 @@ class GPM:
@staticmethod
def
_validate_name_email
(
email
,
name
):
"""
Validate the name and email, exits if both are empty
:param email: The email to validate
:param name: The name to validate
:return: None
"""
if
not
name
and
not
email
:
print
(
f
"
{
colorama
.
Fore
.
YELLOW
}
No current profile set
{
colorama
.
Style
.
RESET_ALL
}
"
)
sys
.
exit
(
1
)
def
current_remove
(
self
):
"""
Remove the current profile from the list of profiles if it exists
:return: None
"""
local_profile
=
self
.
load_git_profile
()
if
not
local_profile
:
print
(
f
"
{
colorama
.
Fore
.
YELLOW
}
No current profile set
{
colorama
.
Style
.
RESET_ALL
}
"
)
...
...
@@ -331,12 +433,24 @@ class GPM:
print
(
out_text
)
def
_validate_query_profile_or_exit
(
self
,
email
):
"""
Validate the query profile or exit if it does not exist
:param email: The email to validate
:return: The profile if it exists, otherwise exits
"""
if
not
(
profile
:
=
self
.
match_query_to_profile
(
email
)):
print
(
f
"
{
colorama
.
Fore
.
RED
}
No matching profile found for current git config
{
colorama
.
Style
.
RESET_ALL
}
"
)
sys
.
exit
(
1
)
return
profile
def
current_import
(
self
,
name
=
None
,
email
=
None
,
comment
=
None
):
"""
Import the current profile from the git config
:param name: If provided, the new name for the profile
:param email: If provided, the new email for the profile
:param comment: If provided, the new comment for the profile
:return: None
"""
profile
=
self
.
load_git_profile
()
if
not
profile
:
print
(
f
"
{
colorama
.
Fore
.
YELLOW
}
No current profile set
{
colorama
.
Style
.
RESET_ALL
}
"
)
...
...
@@ -364,6 +478,10 @@ class GPM:
print
(
f
"
{
colorama
.
Fore
.
GREEN
}
Imported profile:
{
self
.
get_profile_format
(
profile
)
}{
colorama
.
Style
.
RESET_ALL
}
"
)
def
run
(
self
):
"""
Run the Git Profile Manager
:return: None
"""
parser
=
setup
()
args
=
parser
.
parse_args
()
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment