Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Gepetto
dashboard
Commits
03989f7e
Commit
03989f7e
authored
Feb 15, 2018
by
Guilhem Saurel
Browse files
Contributors
parent
8362a642
Changes
7
Hide whitespace changes
Inline
Side-by-side
rainboard/migrations/0004_contributor_contributormail_contributorname.py
0 → 100644
View file @
03989f7e
# Generated by Django 2.0.2 on 2018-02-15 18:19
from
django.db
import
migrations
,
models
import
django.db.models.deletion
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'rainboard'
,
'0003_image'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'Contributor'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'projects'
,
models
.
ManyToManyField
(
to
=
'rainboard.Project'
)),
],
),
migrations
.
CreateModel
(
name
=
'ContributorMail'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'mail'
,
models
.
EmailField
(
max_length
=
254
,
unique
=
True
)),
(
'invalid'
,
models
.
BooleanField
(
default
=
False
)),
(
'contributor'
,
models
.
ForeignKey
(
blank
=
True
,
null
=
True
,
on_delete
=
django
.
db
.
models
.
deletion
.
CASCADE
,
to
=
'rainboard.Contributor'
)),
],
),
migrations
.
CreateModel
(
name
=
'ContributorName'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'name'
,
models
.
CharField
(
max_length
=
200
,
unique
=
True
)),
(
'contributor'
,
models
.
ForeignKey
(
blank
=
True
,
null
=
True
,
on_delete
=
django
.
db
.
models
.
deletion
.
CASCADE
,
to
=
'rainboard.Contributor'
)),
],
),
]
rainboard/models.py
View file @
03989f7e
...
...
@@ -15,7 +15,7 @@ from autoslug import AutoSlugField
from
ndh.models
import
Links
,
NamedModel
,
TimeStampedModel
from
ndh.utils
import
enum_to_choices
,
query_sum
from
.utils
import
SOURCES
,
TARGETS
,
api_next
,
slugify_with_dots
from
.utils
import
SOURCES
,
TARGETS
,
api_next
,
slugify_with_dots
,
invalid_mail
logger
=
logging
.
getLogger
(
'rainboard.models'
)
...
...
@@ -266,6 +266,17 @@ class Project(Links, NamedModel, TimeStampedModel):
def
gitlabciyml
(
self
):
return
get_template
(
'rainboard/gitlab-ci.yml'
).
render
({
'project'
:
self
})
def
contributors
(
self
,
update
=
False
):
if
self
.
main_branch
()
is
None
:
return
[]
if
update
:
for
guy
in
self
.
git
().
git
.
shortlog
(
'-nse'
).
split
(
'
\n
'
):
name
,
mail
=
guy
[
7
:
-
1
].
split
(
' <'
)
contributor
=
get_contributor
(
name
,
mail
)
contributor
.
projects
.
add
(
self
)
contributor
.
save
()
return
self
.
contributor_set
.
all
()
class
Repo
(
TimeStampedModel
):
name
=
models
.
CharField
(
max_length
=
200
)
...
...
@@ -643,10 +654,41 @@ class Tag(models.Model):
ordering
=
(
'name'
,)
unique_together
=
(
'name'
,
'project'
)
# TODO: later
# class Dockerfile(NamedModel, TimeStampedModel):
# project = models.ForeignKey(Project, on_delete=models.CASCADE)
# target = models.PositiveSmallIntegerField(choices=enum_to_choices(TARGETS))
class
Contributor
(
models
.
Model
):
projects
=
models
.
ManyToManyField
(
Project
)
def
__str__
(
self
):
name
=
self
.
contributorname_set
.
first
()
mail
=
self
.
contributormail_set
.
first
()
return
f
'
{
name
}
<
{
mail
}
>'
def
names
(
self
):
return
', '
.
join
(
str
(
name
)
for
name
in
self
.
contributorname_set
.
all
())
def
mails
(
self
):
return
', '
.
join
(
str
(
mail
)
for
mail
in
self
.
contributormail_set
.
filter
(
invalid
=
False
))
def
contributed
(
self
):
return
', '
.
join
(
str
(
project
)
for
project
in
self
.
projects
.
all
())
class
ContributorName
(
models
.
Model
):
contributor
=
models
.
ForeignKey
(
Contributor
,
on_delete
=
models
.
CASCADE
,
blank
=
True
,
null
=
True
)
name
=
models
.
CharField
(
max_length
=
200
,
unique
=
True
)
def
__str__
(
self
):
return
self
.
name
class
ContributorMail
(
models
.
Model
):
contributor
=
models
.
ForeignKey
(
Contributor
,
on_delete
=
models
.
CASCADE
,
blank
=
True
,
null
=
True
)
mail
=
models
.
EmailField
(
unique
=
True
)
invalid
=
models
.
BooleanField
(
default
=
False
)
def
__str__
(
self
):
return
self
.
mail
def
get_default_forge
(
project
):
...
...
@@ -728,3 +770,46 @@ def update_travis(namespace, data):
else
:
repo
.
travis_id
=
data
[
'id'
]
repo
.
save
()
def
get_contributor
(
name
,
mail
):
cname
,
name_created
=
ContributorName
.
objects
.
get_or_create
(
name
=
name
)
cmail
,
mail_created
=
ContributorMail
.
objects
.
get_or_create
(
mail
=
mail
,
defaults
=
{
'invalid'
:
invalid_mail
(
mail
)})
if
name_created
or
mail_created
:
if
name_created
and
mail_created
:
contributor
=
Contributor
.
objects
.
create
()
cname
.
contributor
=
contributor
cmail
.
contributor
=
contributor
cname
.
save
()
cmail
.
save
()
if
mail_created
:
contributor
=
cname
.
contributor
cmail
.
contributor
=
contributor
cmail
.
save
()
if
name_created
:
contributor
=
cmail
.
contributor
cname
.
contributor
=
cmail
.
contributor
cname
.
save
()
elif
cname
.
contributor
==
cmail
.
contributor
or
invalid_mail
(
mail
):
contributor
=
cname
.
contributor
elif
cname
.
contributor
is
None
and
cmail
.
contributor
is
not
None
:
contributor
=
cmail
.
contributor
cname
.
contributor
=
contributor
cname
.
save
()
elif
cmail
.
contributor
is
None
:
contributor
=
cname
.
contributor
cmail
.
contributor
=
contributor
cmail
.
save
()
else
:
contributor
,
fake
=
cname
.
contributor
,
cmail
.
contributor
logger
.
warning
(
f
'merging
{
contributor
}
&
{
fake
}
'
)
if
fake
.
id
<
contributor
.
id
:
contributor
,
fake
=
fake
,
contributor
for
n
in
fake
.
contributorname_set
.
all
():
n
.
contributor
=
contributor
n
.
save
()
for
m
in
fake
.
contributormail_set
.
all
():
m
.
contributor
=
contributor
m
.
save
()
fake
.
delete
()
return
contributor
rainboard/tables.py
View file @
03989f7e
...
...
@@ -93,3 +93,12 @@ class ImageTable(StrippedTable):
class
Meta
:
model
=
models
.
Image
fields
=
(
'robotpkg'
,
'target'
,
'image'
,
'created'
)
class
ContributorTable
(
StrippedTable
):
names
=
tables
.
Column
(
accessor
=
'names'
,
orderable
=
False
)
mails
=
tables
.
Column
(
accessor
=
'mails'
,
orderable
=
False
)
class
Meta
:
model
=
models
.
Contributor
fields
=
(
'names'
,
'mails'
)
rainboard/templates/rainboard/project_detail.html
View file @
03989f7e
...
...
@@ -33,10 +33,11 @@
</div>
<ul
class=
"nav nav-tabs"
>
<li
role=
"presentation"
{%
if
'
robotpkg
'
in
request.path
%}
class=
"active"
{%
endif
%}
><a
href=
"{% url 'rainboard:project' slug=project.slug %}"
>
Robotpkg
</a></h2></li>
<li
role=
"presentation"
{%
if
'
repos
'
in
request.path
%}
class=
"active"
{%
endif
%}
><a
href=
"{% url 'rainboard:project-repos' slug=project.slug %}"
>
Repos
</a></h2></li>
<li
role=
"presentation"
{%
if
'
branches
'
in
request.path
%}
class=
"active"
{%
endif
%}
><a
href=
"{% url 'rainboard:project-branches' slug=project.slug %}"
>
Branches
</a></h2></li>
<li
role=
"presentation"
{%
if
'
images
'
in
request.path
%}
class=
"active"
{%
endif
%}
><a
href=
"{% url 'rainboard:project-images' slug=project.slug %}"
>
Images
</a></h2></li>
<li
role=
"presentation"
{%
if
'
robotpkg
'
in
request.path
%}
class=
"active"
{%
endif
%}
><a
href=
"{% url 'rainboard:project' slug=project.slug %}"
>
Robotpkg
</a></h2></li>
<li
role=
"presentation"
{%
if
'
repos
'
in
request.path
%}
class=
"active"
{%
endif
%}
><a
href=
"{% url 'rainboard:project-repos' slug=project.slug %}"
>
Repos
</a></h2></li>
<li
role=
"presentation"
{%
if
'
branches
'
in
request.path
%}
class=
"active"
{%
endif
%}
><a
href=
"{% url 'rainboard:project-branches' slug=project.slug %}"
>
Branches
</a></h2></li>
<li
role=
"presentation"
{%
if
'
images
'
in
request.path
%}
class=
"active"
{%
endif
%}
><a
href=
"{% url 'rainboard:project-images' slug=project.slug %}"
>
Images
</a></h2></li>
<li
role=
"presentation"
{%
if
'
contributors
'
in
request.path
%}
class=
"active"
{%
endif
%}
><a
href=
"{% url 'rainboard:project-contributors' slug=project.slug %}"
>
Contributors
</a></h2></li>
</ul>
{% if table %}
...
...
rainboard/urls.py
View file @
03989f7e
...
...
@@ -15,4 +15,5 @@ urlpatterns = [
path
(
'project/<str:slug>/repos'
,
views
.
ProjectReposView
.
as_view
(),
name
=
'project-repos'
),
path
(
'project/<str:slug>/branches'
,
views
.
ProjectBranchesView
.
as_view
(),
name
=
'project-branches'
),
path
(
'project/<str:slug>/images'
,
views
.
ProjectImagesView
.
as_view
(),
name
=
'project-images'
),
path
(
'project/<str:slug>/contributors'
,
views
.
ProjectContributorsView
.
as_view
(),
name
=
'project-contributors'
),
]
rainboard/utils.py
View file @
03989f7e
...
...
@@ -11,6 +11,7 @@ logger = logging.getLogger('rainboard.utils')
SOURCES
=
IntEnum
(
'Sources'
,
'github gitlab redmine robotpkg travis'
)
TARGETS
=
IntEnum
(
'Targets'
,
'14.04 16.04 17.10 18.04 dubnium'
)
INVALID_MAILS
=
(
'localhost'
,
'none'
)
def
slugify_with_dots
(
value
):
...
...
@@ -58,3 +59,7 @@ def update_robotpkg(path):
except
git
.
exc
.
GitCommandError
:
logger
.
error
(
'Network error, retrying…'
)
git
.
Repo
(
str
(
path
/
'wip'
/
'.git'
)).
remotes
.
origin
.
pull
()
def
invalid_mail
(
mail
):
return
any
(
invalid
in
mail
for
invalid
in
INVALID_MAILS
)
rainboard/views.py
View file @
03989f7e
...
...
@@ -71,3 +71,10 @@ class ProjectImagesView(ProjectTableView):
def
get_object_list
(
self
):
return
models
.
Image
.
objects
.
filter
(
robotpkg__project
=
self
.
object
)
class
ProjectContributorsView
(
ProjectTableView
):
table_class
=
tables
.
ContributorTable
def
get_object_list
(
self
):
return
self
.
object
.
contributors
()
Write
Preview
Supports
Markdown
0%
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!
Cancel
Please
register
or
sign in
to comment