Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
heptapod
heptapod
Commits
7ec169601dd4
Commit
7ec16960
authored
Feb 06, 2020
by
GitLab Bot
Browse files
Add latest changes from gitlab-org/gitlab@master
parent
973f1f888de5
Changes
96
Hide whitespace changes
Inline
Side-by-side
.gitlab/ci/pages.gitlab-ci.yml
View file @
7ec16960
...
...
@@ -2,6 +2,32 @@
.if-canonical-dot-com-gitlab-org-group-master-refs
:
&if-canonical-dot-com-gitlab-org-group-master-refs
if
:
'
$CI_SERVER_HOST
==
"gitlab.com"
&&
$CI_PROJECT_NAMESPACE
==
"gitlab-org"
&&
$CI_COMMIT_REF_NAME
==
"master"'
# Make sure to update all the similar patterns in other CI config files if you modify these patterns
.code-backstage-qa-patterns
:
&code-backstage-qa-patterns
-
"
.gitlab/ci/**/*"
-
"
.{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
-
"
.{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml"
-
"
.csscomb.json"
-
"
Dockerfile.assets"
-
"
*_VERSION"
-
"
Gemfile{,.lock}"
-
"
Rakefile"
-
"
{babel.config,jest.config}.js"
-
"
config.ru"
-
"
{package.json,yarn.lock}"
-
"
{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
-
"
doc/api/graphql/reference/*"
# Files in this folder are auto-generated
# Backstage changes
-
"
Dangerfile"
-
"
danger/**/*"
-
"
{,ee/}fixtures/**/*"
-
"
{,ee/}rubocop/**/*"
-
"
{,ee/}spec/**/*"
-
"
doc/README.md"
# Some RSpec test rely on this file
# QA changes
-
"
.dockerignore"
-
"
qa/**/*"
pages
:
extends
:
-
.default-tags
...
...
@@ -9,6 +35,7 @@
-
.default-cache
rules
:
-
<<
:
*if-canonical-dot-com-gitlab-org-group-master-refs
changes
:
*code-backstage-qa-patterns
when
:
on_success
stage
:
pages
dependencies
:
[
"
coverage"
,
"
karma"
,
"
gitlab:assets:compile
pull-cache"
]
...
...
.gitlab/ci/rails.gitlab-ci.yml
View file @
7ec16960
...
...
@@ -68,6 +68,7 @@
-
rspec_profiling/
-
tmp/capybara/
-
tmp/memory_test/
-
junit_rspec.xml
reports
:
junit
:
junit_rspec.xml
...
...
Gemfile
View file @
7ec16960
...
...
@@ -488,3 +488,8 @@
gem
'
lru_redux
'
gem
'
erubi
'
,
'~> 1.9.0'
# Locked as long as quoted-printable encoding issues are not resolved
# Monkey-patched in `config/initializers/mail_encoding_patch.rb`
# See https://gitlab.com/gitlab-org/gitlab/issues/197386
gem
'
mail
'
,
'= 2.7.1'
Gemfile.lock
View file @
7ec16960
...
...
@@ -1283,6 +1283,7 @@
lograge (~> 0.5)
loofah (~> 2.2)
lru_redux
mail (= 2.7.1)
mail_room (~> 0.10.0)
marginalia (~> 1.8.0)
memory_profiler (~> 0.9)
...
...
app/assets/javascripts/api.js
View file @
7ec16960
...
...
@@ -45,6 +45,7 @@
mergeRequestsPipeline
:
'
/api/:version/projects/:id/merge_requests/:merge_request_iid/pipelines
'
,
adminStatisticsPath
:
'
/api/:version/application/statistics
'
,
pipelineSinglePath
:
'
/api/:version/projects/:id/pipelines/:pipeline_id
'
,
lsifPath
:
'
/api/:version/projects/:id/commits/:commit_id/lsif/info
'
,
group
(
groupId
,
callback
)
{
const
url
=
Api
.
buildUrl
(
Api
.
groupPath
).
replace
(
'
:id
'
,
groupId
);
...
...
@@ -457,6 +458,14 @@
return
axios
.
get
(
url
);
},
lsifData
(
projectPath
,
commitId
,
path
)
{
const
url
=
Api
.
buildUrl
(
this
.
lsifPath
)
.
replace
(
'
:id
'
,
encodeURIComponent
(
projectPath
))
.
replace
(
'
:commit_id
'
,
commitId
);
return
axios
.
get
(
url
,
{
params
:
{
path
}
});
},
buildUrl
(
url
)
{
return
joinPaths
(
gon
.
relative_url_root
||
''
,
url
.
replace
(
'
:version
'
,
gon
.
api_version
));
},
...
...
app/assets/javascripts/boards/components/issue_count.vue
View file @
7ec16960
...
...
@@ -25,7 +25,7 @@
</
script
>
<
template
>
<div
class=
"issue-count"
>
<div
class=
"issue-count
text-nowrap
"
>
<span
class=
"js-issue-size"
:class=
"
{ 'text-danger': issuesExceedMax }">
{{
issuesSize
}}
</span>
...
...
app/assets/javascripts/code_navigation/components/app.vue
0 → 100644
View file @
7ec16960
<
script
>
import
{
mapActions
,
mapState
}
from
'
vuex
'
;
import
Popover
from
'
./popover.vue
'
;
export
default
{
components
:
{
Popover
,
},
computed
:
{
...
mapState
([
'
currentDefinition
'
,
'
currentDefinitionPosition
'
]),
},
mounted
()
{
this
.
blobViewer
=
document
.
querySelector
(
'
.blob-viewer
'
);
this
.
addGlobalEventListeners
();
this
.
fetchData
();
},
beforeDestroy
()
{
this
.
removeGlobalEventListeners
();
},
methods
:
{
...
mapActions
([
'
fetchData
'
,
'
showDefinition
'
]),
addGlobalEventListeners
()
{
if
(
this
.
blobViewer
)
{
this
.
blobViewer
.
addEventListener
(
'
click
'
,
this
.
showDefinition
);
}
},
removeGlobalEventListeners
()
{
if
(
this
.
blobViewer
)
{
this
.
blobViewer
.
removeEventListener
(
'
click
'
,
this
.
showDefinition
);
}
},
},
};
</
script
>
<
template
>
<popover
v-if=
"currentDefinition"
:position=
"currentDefinitionPosition"
:data=
"currentDefinition"
/>
</
template
>
app/assets/javascripts/code_navigation/components/popover.vue
0 → 100644
View file @
7ec16960
<
script
>
import
{
GlButton
}
from
'
@gitlab/ui
'
;
export
default
{
components
:
{
GlButton
,
},
props
:
{
position
:
{
type
:
Object
,
required
:
true
,
},
data
:
{
type
:
Object
,
required
:
true
,
},
},
data
()
{
return
{
offsetLeft
:
0
,
};
},
computed
:
{
positionStyles
()
{
return
{
left
:
`
${
this
.
position
.
x
-
this
.
offsetLeft
}
px`
,
top
:
`
${
this
.
position
.
y
+
this
.
position
.
height
}
px`
,
};
},
},
watch
:
{
position
:
{
handler
()
{
this
.
$nextTick
(()
=>
this
.
updateOffsetLeft
());
},
deep
:
true
,
immediate
:
true
,
},
},
methods
:
{
updateOffsetLeft
()
{
this
.
offsetLeft
=
Math
.
max
(
0
,
this
.
$el
.
offsetLeft
+
this
.
$el
.
offsetWidth
-
window
.
innerWidth
+
20
,
);
},
},
colorScheme
:
gon
?.
user_color_scheme
,
};
</
script
>
<
template
>
<div
:style=
"positionStyles"
class=
"popover code-navigation-popover popover-font-size-normal gl-popover bs-popover-bottom show"
>
<div
:style=
"
{ left: `${offsetLeft}px` }" class="arrow">
</div>
<div
v-for=
"(hover, index) in data.hover"
:key=
"index"
class=
"border-bottom"
>
<pre
v-if=
"hover.language"
ref=
"code-output"
:class=
"$options.colorScheme"
class=
"border-0 bg-transparent m-0 code highlight"
v-html=
"hover.value"
></pre>
<p
v-else
ref=
"doc-output"
class=
"p-3 m-0"
>
{{
hover
.
value
}}
</p>
</div>
<div
v-if=
"data.definition_url"
class=
"popover-body"
>
<gl-button
:href=
"data.definition_url"
target=
"_blank"
class=
"w-100"
variant=
"default"
>
{{
__
(
'
Go to definition
'
)
}}
</gl-button>
</div>
</div>
</
template
>
app/assets/javascripts/code_navigation/index.js
0 → 100644
View file @
7ec16960
import
Vue
from
'
vue
'
;
import
Vuex
from
'
vuex
'
;
import
store
from
'
./store
'
;
import
App
from
'
./components/app.vue
'
;
Vue
.
use
(
Vuex
);
export
default
()
=>
{
const
el
=
document
.
getElementById
(
'
js-code-navigation
'
);
store
.
dispatch
(
'
setInitialData
'
,
el
.
dataset
);
return
new
Vue
({
el
,
store
,
render
(
h
)
{
return
h
(
App
);
},
});
};
app/assets/javascripts/code_navigation/store/actions.js
0 → 100644
View file @
7ec16960
import
api
from
'
~/api
'
;
import
{
__
}
from
'
~/locale
'
;
import
createFlash
from
'
~/flash
'
;
import
*
as
types
from
'
./mutation_types
'
;
import
{
getCurrentHoverElement
,
setCurrentHoverElement
,
addInteractionClass
}
from
'
../utils
'
;
export
default
{
setInitialData
({
commit
},
data
)
{
commit
(
types
.
SET_INITIAL_DATA
,
data
);
},
requestDataError
({
commit
})
{
commit
(
types
.
REQUEST_DATA_ERROR
);
createFlash
(
__
(
'
An error occurred loading code navigation
'
));
},
fetchData
({
commit
,
dispatch
,
state
})
{
commit
(
types
.
REQUEST_DATA
);
api
.
lsifData
(
state
.
projectPath
,
state
.
commitId
,
state
.
path
)
.
then
(({
data
})
=>
{
const
normalizedData
=
data
.
reduce
((
acc
,
d
)
=>
{
if
(
d
.
hover
)
{
acc
[
`
${
d
.
start_line
}
:
${
d
.
start_char
}
`
]
=
d
;
addInteractionClass
(
d
);
}
return
acc
;
},
{});
commit
(
types
.
REQUEST_DATA_SUCCESS
,
normalizedData
);
})
.
catch
(()
=>
dispatch
(
'
requestDataError
'
));
},
showDefinition
({
commit
,
state
},
{
target
:
el
})
{
let
definition
;
let
position
;
if
(
!
state
.
data
)
return
;
const
isCurrentElementPopoverOpen
=
el
.
classList
.
contains
(
'
hll
'
);
if
(
getCurrentHoverElement
())
{
getCurrentHoverElement
().
classList
.
remove
(
'
hll
'
);
}
if
(
el
.
classList
.
contains
(
'
js-code-navigation
'
)
&&
!
isCurrentElementPopoverOpen
)
{
const
{
lineIndex
,
charIndex
}
=
el
.
dataset
;
position
=
{
x
:
el
.
offsetLeft
,
y
:
el
.
offsetTop
,
height
:
el
.
offsetHeight
,
};
definition
=
state
.
data
[
`
${
lineIndex
}
:
${
charIndex
}
`
];
el
.
classList
.
add
(
'
hll
'
);
setCurrentHoverElement
(
el
);
}
commit
(
types
.
SET_CURRENT_DEFINITION
,
{
definition
,
position
});
},
};
app/assets/javascripts/code_navigation/store/index.js
0 → 100644
View file @
7ec16960
import
Vuex
from
'
vuex
'
;
import
createState
from
'
./state
'
;
import
actions
from
'
./actions
'
;
import
mutations
from
'
./mutations
'
;
export
default
new
Vuex
.
Store
({
actions
,
mutations
,
state
:
createState
(),
});
app/assets/javascripts/code_navigation/store/mutation_types.js
0 → 100644
View file @
7ec16960
export
const
SET_INITIAL_DATA
=
'
SET_INITIAL_DATA
'
;
export
const
REQUEST_DATA
=
'
REQUEST_DATA
'
;
export
const
REQUEST_DATA_SUCCESS
=
'
REQUEST_DATA_SUCCESS
'
;
export
const
REQUEST_DATA_ERROR
=
'
REQUEST_DATA_ERROR
'
;
export
const
SET_CURRENT_DEFINITION
=
'
SET_CURRENT_DEFINITION
'
;
app/assets/javascripts/code_navigation/store/mutations.js
0 → 100644
View file @
7ec16960
import
*
as
types
from
'
./mutation_types
'
;
export
default
{
[
types
.
SET_INITIAL_DATA
](
state
,
{
projectPath
,
commitId
,
blobPath
})
{
state
.
projectPath
=
projectPath
;
state
.
commitId
=
commitId
;
state
.
blobPath
=
blobPath
;
},
[
types
.
REQUEST_DATA
](
state
)
{
state
.
loading
=
true
;
},
[
types
.
REQUEST_DATA_SUCCESS
](
state
,
data
)
{
state
.
loading
=
false
;
state
.
data
=
data
;
},
[
types
.
REQUEST_DATA_ERROR
](
state
)
{
state
.
loading
=
false
;
},
[
types
.
SET_CURRENT_DEFINITION
](
state
,
{
definition
,
position
})
{
state
.
currentDefinition
=
definition
;
state
.
currentDefinitionPosition
=
position
;
},
};
app/assets/javascripts/code_navigation/store/state.js
0 → 100644
View file @
7ec16960
export
default
()
=>
({
projectPath
:
null
,
commitId
:
null
,
blobPath
:
null
,
loading
:
false
,
data
:
null
,
currentDefinition
:
null
,
currentDefinitionPosition
:
null
,
});
app/assets/javascripts/code_navigation/utils/index.js
0 → 100644
View file @
7ec16960
export
const
cachedData
=
new
Map
();
export
const
getCurrentHoverElement
=
()
=>
cachedData
.
get
(
'
current
'
);
export
const
setCurrentHoverElement
=
el
=>
cachedData
.
set
(
'
current
'
,
el
);
export
const
addInteractionClass
=
d
=>
{
let
charCount
=
0
;
const
line
=
document
.
getElementById
(
`LC
${
d
.
start_line
+
1
}
`
);
const
el
=
[...
line
.
childNodes
].
find
(({
textContent
})
=>
{
if
(
charCount
===
d
.
start_char
)
return
true
;
charCount
+=
textContent
.
length
;
return
false
;
});
if
(
el
)
{
el
.
setAttribute
(
'
data-char-index
'
,
d
.
start_char
);
el
.
setAttribute
(
'
data-line-index
'
,
d
.
start_line
);
el
.
classList
.
add
(
'
cursor-pointer
'
,
'
code-navigation
'
,
'
js-code-navigation
'
);
}
};
app/assets/javascripts/pages/projects/blob/show/index.js
View file @
7ec16960
...
...
@@ -30,4 +30,9 @@
}
GpgBadges
.
fetch
();
if
(
gon
.
features
?.
codeNavigation
)
{
// eslint-disable-next-line promise/catch-or-return
import
(
'
~/code_navigation
'
).
then
(
m
=>
m
.
default
());
}
});
app/assets/javascripts/reports/components/modal.vue
View file @
7ec16960
...
...
@@ -46,8 +46,8 @@
</a>
</
template
>
<
template
v-else-if=
"field.type === $options.fieldTypes.
mili
seconds"
>
{{
sprintf
(
__
(
'
%{value
}
m
s
'
),
{
value
:
field
.
value
}
)
<
template
v-else-if=
"field.type === $options.fieldTypes.seconds"
>
{{
sprintf
(
__
(
'
%{value
}
s
'
),
{
value
:
field
.
value
}
)
}}
<
/template
>
<
template
v
-
else
-
if
=
"
field.type === $options.fieldTypes.text
"
>
...
...
app/assets/javascripts/reports/constants.js
View file @
7ec16960
export
const
fieldTypes
=
{
codeBock
:
'
codeBlock
'
,
link
:
'
link
'
,
mili
seconds
:
'
mili
seconds
'
,
seconds
:
'
seconds
'
,
text
:
'
text
'
,
};
...
...
app/assets/javascripts/reports/store/state.js
View file @
7ec16960
...
...
@@ -48,7 +48,7 @@
execution_time
:
{
value
:
null
,
text
:
s__
(
'
Reports|Execution time
'
),
type
:
fieldTypes
.
mili
seconds
,
type
:
fieldTypes
.
seconds
,
},
failure
:
{
value
:
null
,
...
...
app/assets/javascripts/user_popovers.js
View file @
7ec16960
...
...
@@ -54,5 +54,7 @@
);
};
const
initializedPopovers
=
new
Map
();
export
default
(
elements
=
document
.
querySelectorAll
(
'
.js-user-link
'
))
=>
{
const
userLinks
=
Array
.
from
(
elements
);
...
...
@@ -57,4 +59,5 @@
export
default
(
elements
=
document
.
querySelectorAll
(
'
.js-user-link
'
))
=>
{
const
userLinks
=
Array
.
from
(
elements
);
const
UserPopoverComponent
=
Vue
.
extend
(
UserPopover
);
return
userLinks
.
map
(
el
=>
{
...
...
@@ -59,6 +62,9 @@
return
userLinks
.
map
(
el
=>
{
const
UserPopoverComponent
=
Vue
.
extend
(
UserPopover
);
if
(
initializedPopovers
.
has
(
el
))
{
return
initializedPopovers
.
get
(
el
);
}
const
user
=
{
location
:
null
,
bio
:
null
,
...
...
@@ -73,6 +79,8 @@
},
});
initializedPopovers
.
set
(
el
,
renderedPopover
);
renderedPopover
.
$mount
();
el
.
addEventListener
(
'
mouseenter
'
,
({
target
})
=>
{
...
...
Prev
1
2
3
4
5
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a 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