Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
08706f68
Commit
08706f68
authored
May 08, 2017
by
Douwe Maan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement auxiliary blob viewers
parent
62c93ab9
Changes
31
Show whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
598 additions
and
134 deletions
+598
-134
app/assets/javascripts/blob/viewer/index.js
app/assets/javascripts/blob/viewer/index.js
+62
-37
app/controllers/concerns/renders_blob.rb
app/controllers/concerns/renders_blob.rb
+4
-1
app/helpers/projects_helper.rb
app/helpers/projects_helper.rb
+2
-5
app/models/blob.rb
app/models/blob.rb
+22
-12
app/models/blob_viewer/auxiliary.rb
app/models/blob_viewer/auxiliary.rb
+12
-0
app/models/blob_viewer/base.rb
app/models/blob_viewer/base.rb
+22
-8
app/models/blob_viewer/gitlab_ci_yml.rb
app/models/blob_viewer/gitlab_ci_yml.rb
+23
-0
app/models/blob_viewer/license.rb
app/models/blob_viewer/license.rb
+23
-0
app/models/blob_viewer/route_map.rb
app/models/blob_viewer/route_map.rb
+30
-0
app/models/blob_viewer/server_side.rb
app/models/blob_viewer/server_side.rb
+6
-0
app/models/repository.rb
app/models/repository.rb
+9
-2
app/views/projects/blob/_blob.html.haml
app/views/projects/blob/_blob.html.haml
+5
-0
app/views/projects/blob/_viewer.html.haml
app/views/projects/blob/_viewer.html.haml
+1
-2
app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
+9
-0
app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml
...ws/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml
+4
-0
app/views/projects/blob/viewers/_license.html.haml
app/views/projects/blob/viewers/_license.html.haml
+8
-0
app/views/projects/blob/viewers/_loading.html.haml
app/views/projects/blob/viewers/_loading.html.haml
+2
-0
app/views/projects/blob/viewers/_loading_auxiliary.html.haml
app/views/projects/blob/viewers/_loading_auxiliary.html.haml
+2
-0
app/views/projects/blob/viewers/_route_map.html.haml
app/views/projects/blob/viewers/_route_map.html.haml
+9
-0
app/views/projects/blob/viewers/_route_map_loading.html.haml
app/views/projects/blob/viewers/_route_map_loading.html.haml
+4
-0
doc/ci/environments.md
doc/ci/environments.md
+2
-1
lib/gitlab/file_detector.rb
lib/gitlab/file_detector.rb
+2
-1
spec/features/projects/blobs/blob_show_spec.rb
spec/features/projects/blobs/blob_show_spec.rb
+78
-20
spec/models/blob_spec.rb
spec/models/blob_spec.rb
+46
-0
spec/models/blob_viewer/base_spec.rb
spec/models/blob_viewer/base_spec.rb
+38
-34
spec/models/blob_viewer/gitlab_ci_yml_spec.rb
spec/models/blob_viewer/gitlab_ci_yml_spec.rb
+32
-0
spec/models/blob_viewer/license_spec.rb
spec/models/blob_viewer/license_spec.rb
+34
-0
spec/models/blob_viewer/route_map_spec.rb
spec/models/blob_viewer/route_map_spec.rb
+38
-0
spec/models/blob_viewer/server_side_spec.rb
spec/models/blob_viewer/server_side_spec.rb
+25
-0
spec/models/repository_spec.rb
spec/models/repository_spec.rb
+42
-9
spec/views/projects/blob/_viewer.html.haml_spec.rb
spec/views/projects/blob/_viewer.html.haml_spec.rb
+2
-2
No files found.
app/assets/javascripts/blob/viewer/index.js
View file @
08706f68
/* global Flash */
export
default
class
BlobViewer
{
constructor
()
{
BlobViewer
.
initAuxiliaryViewer
();
this
.
initMainViewers
();
}
static
initAuxiliaryViewer
()
{
const
auxiliaryViewer
=
document
.
querySelector
(
'
.blob-viewer[data-type="auxiliary"]
'
);
if
(
!
auxiliaryViewer
)
return
;
BlobViewer
.
loadViewer
(
auxiliaryViewer
);
}
initMainViewers
()
{
this
.
$fileHolder
=
$
(
'
.file-holder
'
);
if
(
!
this
.
$fileHolder
.
length
)
return
;
this
.
switcher
=
document
.
querySelector
(
'
.js-blob-viewer-switcher
'
);
this
.
switcherBtns
=
document
.
querySelectorAll
(
'
.js-blob-viewer-switch-btn
'
);
this
.
copySourceBtn
=
document
.
querySelector
(
'
.js-copy-blob-source-btn
'
);
this
.
simpleViewer
=
document
.
querySelector
(
'
.blob-viewer[data-type="simple"]
'
);
this
.
richViewer
=
document
.
querySelector
(
'
.blob-viewer[data-type="rich"]
'
);
this
.
$fileHolder
=
$
(
'
.file-holder
'
);
const
initialViewer
=
document
.
querySelector
(
'
.blob-viewer:not(.hidden)
'
);
if
(
!
initialViewer
)
return
;
let
initialViewerName
=
initialViewer
.
getAttribute
(
'
data-type
'
);
this
.
simpleViewer
=
this
.
$fileHolder
[
0
].
querySelector
(
'
.blob-viewer[data-type="simple"]
'
);
this
.
richViewer
=
this
.
$fileHolder
[
0
].
querySelector
(
'
.blob-viewer[data-type="rich"]
'
);
this
.
initBindings
();
this
.
switchToInitialViewer
();
}
switchToInitialViewer
()
{
const
initialViewer
=
this
.
$fileHolder
[
0
].
querySelector
(
'
.blob-viewer:not(.hidden)
'
);
let
initialViewerName
=
initialViewer
.
getAttribute
(
'
data-type
'
);
if
(
this
.
switcher
&&
location
.
hash
.
indexOf
(
'
#L
'
)
===
0
)
{
initialViewerName
=
'
simple
'
;
}
...
...
@@ -64,40 +82,13 @@ export default class BlobViewer {
$
(
this
.
copySourceBtn
).
tooltip
(
'
fixTitle
'
);
}
loadViewer
(
viewerParam
)
{
const
viewer
=
viewerParam
;
const
url
=
viewer
.
getAttribute
(
'
data-url
'
);
if
(
!
url
||
viewer
.
getAttribute
(
'
data-loaded
'
)
||
viewer
.
getAttribute
(
'
data-loading
'
))
{
return
;
}
viewer
.
setAttribute
(
'
data-loading
'
,
'
true
'
);
$
.
ajax
({
url
,
dataType
:
'
JSON
'
,
})
.
fail
(()
=>
new
Flash
(
'
Error loading source view
'
))
.
done
((
data
)
=>
{
viewer
.
innerHTML
=
data
.
html
;
$
(
viewer
).
syntaxHighlight
();
viewer
.
setAttribute
(
'
data-loaded
'
,
'
true
'
);
this
.
$fileHolder
.
trigger
(
'
highlight:line
'
);
this
.
toggleCopyButtonState
();
});
}
switchToViewer
(
name
)
{
const
newViewer
=
document
.
querySelector
(
`.blob-viewer[data-type='
${
name
}
']`
);
const
newViewer
=
this
.
$fileHolder
[
0
]
.
querySelector
(
`.blob-viewer[data-type='
${
name
}
']`
);
if
(
this
.
activeViewer
===
newViewer
)
return
;
const
oldButton
=
document
.
querySelector
(
'
.js-blob-viewer-switch-btn.active
'
);
const
newButton
=
document
.
querySelector
(
`.js-blob-viewer-switch-btn[data-viewer='
${
name
}
']`
);
const
oldViewer
=
document
.
querySelector
(
`.blob-viewer:not([data-type='
${
name
}
'])`
);
const
oldViewer
=
this
.
$fileHolder
[
0
]
.
querySelector
(
`.blob-viewer:not([data-type='
${
name
}
'])`
);
if
(
oldButton
)
{
oldButton
.
classList
.
remove
(
'
active
'
);
...
...
@@ -118,6 +109,40 @@ export default class BlobViewer {
this
.
toggleCopyButtonState
();
this
.
loadViewer
(
newViewer
);
BlobViewer
.
loadViewer
(
newViewer
)
.
then
((
viewer
)
=>
{
$
(
viewer
).
syntaxHighlight
();
this
.
$fileHolder
.
trigger
(
'
highlight:line
'
);
this
.
toggleCopyButtonState
();
})
.
catch
(()
=>
new
Flash
(
'
Error loading viewer
'
));
}
static
loadViewer
(
viewerParam
)
{
const
viewer
=
viewerParam
;
const
url
=
viewer
.
getAttribute
(
'
data-url
'
);
return
new
Promise
((
resolve
,
reject
)
=>
{
if
(
!
url
||
viewer
.
getAttribute
(
'
data-loaded
'
)
||
viewer
.
getAttribute
(
'
data-loading
'
))
{
resolve
(
viewer
);
return
;
}
viewer
.
setAttribute
(
'
data-loading
'
,
'
true
'
);
$
.
ajax
({
url
,
dataType
:
'
JSON
'
,
})
.
fail
(
reject
)
.
done
((
data
)
=>
{
viewer
.
innerHTML
=
data
.
html
;
viewer
.
setAttribute
(
'
data-loaded
'
,
'
true
'
);
resolve
(
viewer
);
});
});
}
}
app/controllers/concerns/renders_blob.rb
View file @
08706f68
...
...
@@ -3,8 +3,11 @@ module RendersBlob
def
render_blob_json
(
blob
)
viewer
=
if
params
[
:viewer
]
==
'rich'
case
params
[
:viewer
]
when
'rich'
blob
.
rich_viewer
when
'auxiliary'
blob
.
auxiliary_viewer
else
blob
.
simple_viewer
end
...
...
app/helpers/projects_helper.rb
View file @
08706f68
...
...
@@ -110,11 +110,8 @@ module ProjectsHelper
end
def
license_short_name
(
project
)
return
'LICENSE'
if
project
.
repository
.
license_key
.
nil?
license
=
Licensee
::
License
.
new
(
project
.
repository
.
license_key
)
license
.
nickname
||
license
.
name
license
=
project
.
repository
.
license
license
&
.
nickname
||
license
&
.
name
||
'LICENSE'
end
def
last_push_event
...
...
app/models/blob.rb
View file @
08706f68
...
...
@@ -34,10 +34,13 @@ class Blob < SimpleDelegator
BlobViewer
::
BinarySTL
,
BlobViewer
::
TextSTL
].
freeze
].
sort_by
{
|
v
|
v
.
binary?
?
0
:
1
}.
freeze
BINARY_VIEWERS
=
RICH_VIEWERS
.
select
(
&
:binary?
).
freeze
TEXT_VIEWERS
=
RICH_VIEWERS
.
select
(
&
:text?
).
freeze
AUXILIARY_VIEWERS
=
[
BlobViewer
::
GitlabCiYml
,
BlobViewer
::
RouteMap
,
BlobViewer
::
License
].
freeze
attr_reader
:project
...
...
@@ -154,6 +157,12 @@ class Blob < SimpleDelegator
@rich_viewer
=
rich_viewer_class
&
.
new
(
self
)
end
def
auxiliary_viewer
return
@auxiliary_viewer
if
defined?
(
@auxiliary_viewer
)
@auxiliary_viewer
=
auxiliary_viewer_class
&
.
new
(
self
)
end
def
rendered_as_text?
(
ignore_errors:
true
)
simple_viewer
.
text?
&&
(
ignore_errors
||
simple_viewer
.
render_error
.
nil?
)
end
...
...
@@ -180,17 +189,18 @@ class Blob < SimpleDelegator
end
def
rich_viewer_class
return
if
empty?
||
external_storage_error?
viewer_class_from
(
RICH_VIEWERS
)
end
classes
=
if
stored_externally?
BINARY_VIEWERS
+
TEXT_VIEWERS
elsif
binary?
BINARY_VIEWERS
else
# text
TEXT_VIEWERS
def
auxiliary_viewer_class
viewer_class_from
(
AUXILIARY_VIEWERS
)
end
classes
.
find
{
|
viewer_class
|
viewer_class
.
can_render?
(
self
)
}
def
viewer_class_from
(
classes
)
return
if
empty?
||
external_storage_error?
verify_binary
=
!
stored_externally?
classes
.
find
{
|
viewer_class
|
viewer_class
.
can_render?
(
self
,
verify_binary:
verify_binary
)
}
end
end
app/models/blob_viewer/auxiliary.rb
0 → 100644
View file @
08706f68
module
BlobViewer
module
Auxiliary
extend
ActiveSupport
::
Concern
included
do
self
.
loading_partial_name
=
'loading_auxiliary'
self
.
type
=
:auxiliary
self
.
max_size
=
100
.
kilobytes
self
.
absolute_max_size
=
100
.
kilobytes
end
end
end
app/models/blob_viewer/base.rb
View file @
08706f68
module
BlobViewer
class
Base
class_attribute
:partial_name
,
:type
,
:extensions
,
:client_side
,
:binary
,
:switcher_icon
,
:switcher_title
,
:max_size
,
:absolute_max_si
ze
PARTIAL_PATH_PREFIX
=
'projects/blob/viewers'
.
free
ze
delegate
:partial_path
,
:rich?
,
:simple?
,
:client_side?
,
:server_side?
,
:text?
,
:binary?
,
to: :class
class_attribute
:partial_name
,
:loading_partial_name
,
:type
,
:extensions
,
:file_type
,
:client_side
,
:binary
,
:switcher_icon
,
:switcher_title
,
:max_size
,
:absolute_max_size
self
.
loading_partial_name
=
'loading'
delegate
:partial_path
,
:loading_partial_path
,
:rich?
,
:simple?
,
:client_side?
,
:server_side?
,
:text?
,
:binary?
,
to: :class
attr_reader
:blob
attr_accessor
:override_max_size
...
...
@@ -12,7 +16,11 @@ module BlobViewer
end
def
self
.
partial_path
"projects/blob/viewers/
#{
partial_name
}
"
File
.
join
(
PARTIAL_PATH_PREFIX
,
partial_name
)
end
def
self
.
loading_partial_path
File
.
join
(
PARTIAL_PATH_PREFIX
,
loading_partial_name
)
end
def
self
.
rich?
...
...
@@ -23,6 +31,10 @@ module BlobViewer
type
==
:simple
end
def
self
.
auxiliary?
type
==
:auxiliary
end
def
self
.
client_side?
client_side
end
...
...
@@ -39,8 +51,12 @@ module BlobViewer
!
binary?
end
def
self
.
can_render?
(
blob
)
!
extensions
||
extensions
.
include?
(
blob
.
extension
)
def
self
.
can_render?
(
blob
,
verify_binary:
true
)
return
false
if
verify_binary
&&
binary?
!=
blob
.
binary?
return
true
if
extensions
&
.
include?
(
blob
.
extension
)
return
true
if
file_type
&&
Gitlab
::
FileDetector
.
type_of
(
blob
.
path
)
==
file_type
false
end
def
too_large?
...
...
@@ -83,9 +99,7 @@ module BlobViewer
end
def
prepare!
if
server_side?
&&
blob
.
project
blob
.
load_all_data!
(
blob
.
project
.
repository
)
end
# To be overridden by subclasses
end
private
...
...
app/models/blob_viewer/gitlab_ci_yml.rb
0 → 100644
View file @
08706f68
module
BlobViewer
class
GitlabCiYml
<
Base
include
ServerSide
include
Auxiliary
self
.
partial_name
=
'gitlab_ci_yml'
self
.
loading_partial_name
=
'gitlab_ci_yml_loading'
self
.
file_type
=
:gitlab_ci
self
.
binary
=
false
def
validation_message
return
@validation_message
if
defined?
(
@validation_message
)
prepare!
@validation_message
=
Ci
::
GitlabCiYamlProcessor
.
validation_message
(
blob
.
data
)
end
def
valid?
validation_message
.
blank?
end
end
end
app/models/blob_viewer/license.rb
0 → 100644
View file @
08706f68
module
BlobViewer
class
License
<
Base
# We treat the License viewer as if it renders the content client-side,
# so that it doesn't attempt to load the entire blob contents and is
# rendered synchronously instead of loaded asynchronously.
include
ClientSide
include
Auxiliary
self
.
partial_name
=
'license'
self
.
file_type
=
:license
self
.
binary
=
false
def
license
blob
.
project
.
repository
.
license
end
def
render_error
return
if
license
:unknown_license
end
end
end
app/models/blob_viewer/route_map.rb
0 → 100644
View file @
08706f68
module
BlobViewer
class
RouteMap
<
Base
include
ServerSide
include
Auxiliary
self
.
partial_name
=
'route_map'
self
.
loading_partial_name
=
'route_map_loading'
self
.
file_type
=
:route_map
self
.
binary
=
false
def
validation_message
return
@validation_message
if
defined?
(
@validation_message
)
prepare!
@validation_message
=
begin
Gitlab
::
RouteMap
.
new
(
blob
.
data
)
nil
rescue
Gitlab
::
RouteMap
::
FormatError
=>
e
e
.
message
end
end
def
valid?
validation_message
.
blank?
end
end
end
app/models/blob_viewer/server_side.rb
View file @
08706f68
...
...
@@ -7,5 +7,11 @@ module BlobViewer
self
.
max_size
=
2
.
megabytes
self
.
absolute_max_size
=
5
.
megabytes
end
def
prepare!
if
blob
.
project
blob
.
load_all_data!
(
blob
.
project
.
repository
)
end
end
end
end
app/models/repository.rb
View file @
08706f68
...
...
@@ -549,6 +549,13 @@ class Repository
end
cache_method
:license_key
def
license
return
@license
if
defined?
(
@license
)
return
unless
license_key
@license
=
Licensee
::
License
.
new
(
license_key
)
end
def
gitignore
file_on_head
(
:gitignore
)
end
...
...
@@ -1083,8 +1090,8 @@ class Repository
def
file_on_head
(
type
)
if
head
=
tree
(
:head
)
head
.
blobs
.
find
do
|
file
|
Gitlab
::
FileDetector
.
type_of
(
file
.
name
)
==
type
head
.
blobs
.
find
do
|
blob
|
Gitlab
::
FileDetector
.
type_of
(
blob
.
path
)
==
type
end
end
end
...
...
app/views/projects/blob/_blob.html.haml
View file @
08706f68
...
...
@@ -6,6 +6,11 @@
-
blob_commit
=
@repository
.
last_commit_for_path
(
@commit
.
id
,
blob
.
path
)
=
render
blob_commit
,
project:
@project
,
ref:
@ref
-
auxiliary_viewer
=
blob
.
auxiliary_viewer
-
if
auxiliary_viewer
&&
!
auxiliary_viewer
.
render_error
.well-segment.blob-auxiliary-viewer
=
render
'projects/blob/viewer'
,
viewer:
auxiliary_viewer
#blob-content-holder
.blob-content-holder
%article
.file-holder
=
render
"projects/blob/header"
,
blob:
blob
...
...
app/views/projects/blob/_viewer.html.haml
View file @
08706f68
...
...
@@ -5,8 +5,7 @@
-
viewer_url
=
local_assigns
.
fetch
(
:viewer_url
)
{
url_for
(
params
.
merge
(
viewer:
viewer
.
type
,
format: :json
))
}
if
load_asynchronously
.blob-viewer
{
data:
{
type:
viewer
.
type
,
url:
viewer_url
},
class:
(
'hidden'
if
hidden
)
}
-
if
load_asynchronously
.text-center.prepend-top-default.append-bottom-default
=
icon
(
'spinner spin 2x'
,
'aria-hidden'
=>
'true'
,
'aria-label'
=>
'Loading content'
)
=
render
viewer
.
loading_partial_path
,
viewer:
viewer
-
elsif
render_error
=
render
'projects/blob/render_error'
,
viewer:
viewer
-
else
...
...
app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
0 → 100644
View file @
08706f68
-
if
viewer
.
valid?
=
icon
(
'check fw'
)
This GitLab CI configuration is valid.
-
else
=
icon
(
'warning fw'
)
This GitLab CI configuration is invalid:
=
viewer
.
validation_message
=
link_to
'Learn more'
,
help_page_path
(
'ci/yaml/README'
)
app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml
0 → 100644
View file @
08706f68
=
icon
(
'spinner spin fw'
)
Validating GitLab CI configuration…
=
link_to
'Learn more'
,
help_page_path
(
'ci/yaml/README'
)
app/views/projects/blob/viewers/_license.html.haml
0 → 100644
View file @
08706f68
-
license
=
viewer
.
license
=
icon
(
'balance-scale fw'
)
This project is licensed under the
=
succeed
'.'
do
%strong
=
license
.
name
=
link_to
'Learn more about this license'
,
license
.
url
,
target:
'_blank'
,
rel:
'noopener noreferrer'
app/views/projects/blob/viewers/_loading.html.haml
0 → 100644
View file @
08706f68
.text-center.prepend-top-default.append-bottom-default
=
icon
(
'spinner spin 2x'
,
'aria-hidden'
=>
'true'
,
'aria-label'
=>
'Loading content…'
)
app/views/projects/blob/viewers/_loading_auxiliary.html.haml
0 → 100644
View file @
08706f68
=
icon
(
'spinner spin fw'
)
Loading…
app/views/projects/blob/viewers/_route_map.html.haml
0 → 100644
View file @
08706f68
-
if
viewer
.
valid?
=
icon
(
'check fw'
)
This Route Map is valid.
-
else
=
icon
(
'warning fw'
)
This Route Map is invalid:
=
viewer
.
validation_message
=
link_to
'Learn more'
,
help_page_path
(
'ci/environments'
,
anchor:
'route-map'
)
app/views/projects/blob/viewers/_route_map_loading.html.haml
0 → 100644
View file @
08706f68
=
icon
(
'spinner spin fw'
)
Validating Route Map…
=
link_to
'Learn more'
,
help_page_path
(
'ci/environments'
,
anchor:
'route-map'
)
doc/ci/environments.md
View file @
08706f68
...
...
@@ -442,7 +442,8 @@ and/or `production`) you can see this information in the merge request itself.
![
Environment URLs in merge request
](
img/environments_link_url_mr.png
)
### Go directly from source files to public pages on the environment
### <a name="route-map"></a>Go directly from source files to public pages on the environment
> Introduced in GitLab 8.17.
...
...
lib/gitlab/file_detector.rb
View file @
08706f68
...
...
@@ -13,7 +13,8 @@ module Gitlab
gitignore:
'.gitignore'
,
koding:
'.koding.yml'
,
gitlab_ci:
'.gitlab-ci.yml'
,
avatar:
/\Alogo\.(png|jpg|gif)\z/
avatar:
/\Alogo\.(png|jpg|gif)\z/
,
route_map:
'route-map.yml'
}.
freeze
# Returns an Array of file types based on the given paths.
...
...
spec/features/projects/blobs/blob_show_spec.rb
View file @
08706f68
...
...
@@ -5,13 +5,13 @@ feature 'File blob', :js, feature: true do
def
visit_blob
(
path
,
fragment
=
nil
)
visit
namespace_project_blob_path
(
project
.
namespace
,
project
,
File
.
join
(
'master'
,
path
),
anchor:
fragment
)
wait_for_ajax
end
context
'Ruby file'
do
before
do
visit_blob
(
'files/ruby/popen.rb'
)
wait_for_ajax
end
it
'displays the blob'
do
...
...
@@ -35,8 +35,6 @@ feature 'File blob', :js, feature: true do
context
'visiting directly'
do
before
do
visit_blob
(
'files/markdown/ruby-style-guide.md'
)
wait_for_ajax
end
it
'displays the blob using the rich viewer'
do
...
...
@@ -104,8 +102,6 @@ feature 'File blob', :js, feature: true do
context
'visiting with a line number anchor'
do
before
do
visit_blob
(
'files/markdown/ruby-style-guide.md'
,
'L1'
)
wait_for_ajax
end
it
'displays the blob using the simple viewer'
do
...
...
@@ -148,8 +144,6 @@ feature 'File blob', :js, feature: true do
project
.
update_attribute
(
:lfs_enabled
,
true
)
visit_blob
(
'files/lfs/file.md'
)
wait_for_ajax
end
it
'displays an error'
do
...
...
@@ -198,8 +192,6 @@ feature 'File blob', :js, feature: true do
context
'when LFS is disabled on the project'
do
before
do
visit_blob
(
'files/lfs/file.md'
)
wait_for_ajax
end
it
'displays the blob'
do
...
...
@@ -235,8 +227,6 @@ feature 'File blob', :js, feature: true do
).
execute
visit_blob
(
'files/test.pdf'
)
wait_for_ajax
end
it
'displays the blob'
do
...
...
@@ -263,8 +253,6 @@ feature 'File blob', :js, feature: true do
project
.
update_attribute
(
:lfs_enabled
,
true
)
visit_blob
(
'files/lfs/lfs_object.iso'
)
wait_for_ajax
end
it
'displays the blob'
do
...
...
@@ -287,8 +275,6 @@ feature 'File blob', :js, feature: true do
context
'when LFS is disabled on the project'
do
before
do
visit_blob
(
'files/lfs/lfs_object.iso'
)
wait_for_ajax
end
it
'displays the blob'
do
...
...
@@ -312,8 +298,6 @@ feature 'File blob', :js, feature: true do
context
'ZIP file'
do
before
do
visit_blob
(
'Gemfile.zip'
)
wait_for_ajax
end
it
'displays the blob'
do
...
...
@@ -348,8 +332,6 @@ feature 'File blob', :js, feature: true do
).
execute
visit_blob
(
'files/empty.md'
)
wait_for_ajax
end
it
'displays an error'
do
...
...
@@ -369,4 +351,80 @@ feature 'File blob', :js, feature: true do
end
end
end
context
'.gitlab-ci.yml'
do
before
do
project
.
add_master
(
project
.
creator
)
Files
::
CreateService
.
new
(
project
,
project
.
creator
,
start_branch:
'master'
,
branch_name:
'master'
,
commit_message:
"Add .gitlab-ci.yml"
,
file_path:
'.gitlab-ci.yml'
,
file_content:
File
.
read
(
Rails
.
root
.
join
(
'spec/support/gitlab_stubs/gitlab_ci.yml'
))
).
execute
visit_blob
(
'.gitlab-ci.yml'
)
end
it
'displays an auxiliary viewer'
do
aggregate_failures
do
# shows that configuration is valid
expect
(
page
).
to
have_content
(
'This GitLab CI configuration is valid.'
)
# shows a learn more link
expect
(
page
).
to
have_link
(
'Learn more'
)
end
end
end
context
'.gitlab/route-map.yml'
do
before
do
project
.
add_master
(
project
.
creator
)
Files
::
CreateService
.
new
(
project
,
project
.
creator
,
start_branch:
'master'
,
branch_name:
'master'
,
commit_message:
"Add .gitlab/route-map.yml"
,
file_path:
'.gitlab/route-map.yml'
,
file_content:
<<-
MAP
.
strip_heredoc
# Team data
- source: 'data/team.yml'
public: 'team/'
MAP
).
execute
visit_blob
(
'.gitlab/route-map.yml'
)
end
it
'displays an auxiliary viewer'
do
aggregate_failures
do
# shows that map is valid
expect
(
page
).
to
have_content
(
'This Route Map is valid.'
)
# shows a learn more link
expect
(
page
).
to
have_link
(
'Learn more'
)
end
end
end
context
'LICENSE'
do
before
do
visit_blob
(
'LICENSE'
)
end
it
'displays an auxiliary viewer'
do
aggregate_failures
do
# shows license
expect
(
page
).
to
have_content
(
'This project is licensed under the MIT License.'
)
# shows a learn more link
expect
(
page
).
to
have_link
(
'Learn more about this license'
,
'http://choosealicense.com/licenses/mit/'
)
end
end
end
end
spec/models/blob_spec.rb
View file @
08706f68
...
...
@@ -271,6 +271,52 @@ describe Blob do
end
end
describe
'#auxiliary_viewer'
do
context
'when the blob has an external storage error'
do
before
do
project
.
lfs_enabled
=
false
end
it
'returns nil'
do
blob
=
fake_blob
(
path:
'LICENSE'
,
lfs:
true
)
expect
(
blob
.
auxiliary_viewer
).
to
be_nil
end
end
context
'when the blob is empty'
do
it
'returns nil'
do
blob
=
fake_blob
(
data:
''
)
expect
(
blob
.
auxiliary_viewer
).
to
be_nil
end
end
context
'when the blob is stored externally'
do
it
'returns a matching viewer'
do
blob
=
fake_blob
(
path:
'LICENSE'
,
lfs:
true
)
expect
(
blob
.
auxiliary_viewer
).
to
be_a
(
BlobViewer
::
License
)
end
end
context
'when the blob is binary'
do
it
'returns nil'
do
blob
=
fake_blob
(
path:
'LICENSE'
,
binary:
true
)
expect
(
blob
.
auxiliary_viewer
).
to
be_nil
end
end
context
'when the blob is text-based'
do
it
'returns a matching text-based viewer'
do
blob
=
fake_blob
(
path:
'LICENSE'
)
expect
(
blob
.
auxiliary_viewer
).
to
be_a
(
BlobViewer
::
License
)
end
end
end
describe
'#rendered_as_text?'
do
context
'when ignoring errors'
do
context
'when the simple viewer is text-based'
do
...
...
spec/models/blob_viewer/base_spec.rb
View file @
08706f68
...
...
@@ -8,6 +8,7 @@ describe BlobViewer::Base, model: true do
let
(
:viewer_class
)
do
Class
.
new
(
described_class
)
do
self
.
extensions
=
%w(pdf)
self
.
binary
=
true
self
.
max_size
=
1
.
megabyte
self
.
absolute_max_size
=
5
.
megabytes
self
.
client_side
=
false
...
...
@@ -18,14 +19,47 @@ describe BlobViewer::Base, model: true do
describe
'.can_render?'
do
context
'when the extension is supported'
do
let
(
:blob
)
{
fake_blob
(
path:
'file.pdf'
)
}
context
'when the binaryness matches'
do
let
(
:blob
)
{
fake_blob
(
path:
'file.pdf'
,
binary:
true
)
}
it
'returns true'
do
expect
(
viewer_class
.
can_render?
(
blob
)).
to
be_truthy
end
end
context
'when the extension is not supported'
do
context
'when the binaryness does not match'
do
let
(
:blob
)
{
fake_blob
(
path:
'file.pdf'
,
binary:
false
)
}
it
'returns false'
do
expect
(
viewer_class
.
can_render?
(
blob
)).
to
be_falsey
end
end
end
context
'when the file type is supported'
do
before
do
viewer_class
.
file_type
=
:license
viewer_class
.
binary
=
false
end
context
'when the binaryness matches'
do
let
(
:blob
)
{
fake_blob
(
path:
'LICENSE'
,
binary:
false
)
}
it
'returns true'
do
expect
(
viewer_class
.
can_render?
(
blob
)).
to
be_truthy
end
end
context
'when the binaryness does not match'
do
let
(
:blob
)
{
fake_blob
(
path:
'LICENSE'
,
binary:
true
)
}
it
'returns false'
do
expect
(
viewer_class
.
can_render?
(
blob
)).
to
be_falsey
end
end
end
context
'when the extension and file type are not supported'
do
let
(
:blob
)
{
fake_blob
(
path:
'file.txt'
)
}
it
'returns false'
do
...
...
@@ -153,34 +187,4 @@ describe BlobViewer::Base, model: true do
end
end
end
describe
'#prepare!'
do
context
'when the viewer is server side'
do
let
(
:blob
)
{
fake_blob
(
path:
'file.md'
)
}
before
do
viewer_class
.
client_side
=
false
end
it
'loads all blob data'
do
expect
(
blob
).
to
receive
(
:load_all_data!
)
viewer
.
prepare!
end
end
context
'when the viewer is client side'
do
let
(
:blob
)
{
fake_blob
(
path:
'file.md'
)
}
before
do
viewer_class
.
client_side
=
true
end
it
"doesn't load all blob data"
do
expect
(
blob
).
not_to
receive
(
:load_all_data!
)
viewer
.
prepare!
end
end
end
end
spec/models/blob_viewer/gitlab_ci_yml_spec.rb
0 → 100644
View file @
08706f68
require
'spec_helper'
describe
BlobViewer
::
GitlabCiYml
,
model:
true
do
include
FakeBlobHelpers
let
(
:project
)
{
build
(
:project
)
}
let
(
:data
)
{
File
.
read
(
Rails
.
root
.
join
(
'spec/support/gitlab_stubs/gitlab_ci.yml'
))
}
let
(
:blob
)
{
fake_blob
(
path:
'.gitlab-ci.yml'
,
data:
data
)
}
subject
{
described_class
.
new
(
blob
)
}
describe
'#validation_message'
do
it
'calls prepare! on the viewer'
do
expect
(
subject
).
to
receive
(
:prepare!
)
subject
.
validation_message
end
context
'when the configuration is valid'
do
it
'returns nil'
do
expect
(
subject
.
validation_message
).
to
be_nil
end
end
context
'when the configuration is invalid'
do
let
(
:data
)
{
'oof'
}
it
'returns the error message'
do
expect
(
subject
.
validation_message
).
to
eq
(
'Invalid configuration format'
)
end
end
end
end
spec/models/blob_viewer/license_spec.rb
0 → 100644
View file @
08706f68
require
'spec_helper'
describe
BlobViewer
::
License
,
model:
true
do
include
FakeBlobHelpers
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:blob
)
{
fake_blob
(
path:
'LICENSE'
)
}
subject
{
described_class
.
new
(
blob
)
}
describe
'#license'
do
it
'returns the blob project repository license'
do
expect
(
subject
.
license
).
not_to
be_nil
expect
(
subject
.
license
).
to
eq
(
project
.
repository
.
license
)
end
end
describe
'#render_error'
do
context
'when there is no license'
do
before
do
allow
(
project
.
repository
).
to
receive
(
:license
).
and_return
(
nil
)
end
it
'returns :unknown_license'
do
expect
(
subject
.
render_error
).
to
eq
(
:unknown_license
)
end
end
context
'when there is a license'
do
it
'returns nil'
do
expect
(
subject
.
render_error
).
to
be_nil
end
end
end
end
spec/models/blob_viewer/route_map_spec.rb
0 → 100644
View file @
08706f68
require
'spec_helper'
describe
BlobViewer
::
RouteMap
,
model:
true
do
include
FakeBlobHelpers
let
(
:project
)
{
build
(
:project
)
}
let
(
:data
)
do
<<-
MAP
.
strip_heredoc
# Team data
- source: 'data/team.yml'
public: 'team/'
MAP
end
let
(
:blob
)
{
fake_blob
(
path:
'.gitlab/route-map.yml'
,
data:
data
)
}
subject
{
described_class
.
new
(
blob
)
}
describe
'#validation_message'
do
it
'calls prepare! on the viewer'
do
expect
(
subject
).
to
receive
(
:prepare!
)
subject
.
validation_message
end
context
'when the configuration is valid'
do
it
'returns nil'
do
expect
(
subject
.
validation_message
).
to
be_nil
end
end
context
'when the configuration is invalid'
do
let
(
:data
)
{
'oof'
}
it
'returns the error message'
do
expect
(
subject
.
validation_message
).
to
eq
(
'Route map is not an array'
)
end
end
end
end
spec/models/blob_viewer/server_side_spec.rb
0 → 100644
View file @
08706f68
require
'spec_helper'
describe
BlobViewer
::
ServerSide
,
model:
true
do
include
FakeBlobHelpers
let
(
:project
)
{
build
(
:empty_project
)
}
let
(
:viewer_class
)
do
Class
.
new
(
BlobViewer
::
Base
)
do
include
BlobViewer
::
ServerSide
end
end
subject
{
viewer_class
.
new
(
blob
)
}
describe
'#prepare!'
do
let
(
:blob
)
{
fake_blob
(
path:
'file.txt'
)
}
it
'loads all blob data'
do
expect
(
blob
).
to
receive
(
:load_all_data!
)
subject
.
prepare!
end
end
end
spec/models/repository_spec.rb
View file @
08706f68
...
...
@@ -2,7 +2,7 @@ require 'spec_helper'
describe
Repository
,
models:
true
do
include
RepoHelpers
TestBlob
=
Struct
.
new
(
:
name
)
TestBlob
=
Struct
.
new
(
:
path
)
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:repository
)
{
project
.
repository
}
...
...
@@ -565,31 +565,31 @@ describe Repository, models: true do
it
'accepts changelog'
do
expect
(
repository
.
tree
).
to
receive
(
:blobs
).
and_return
([
TestBlob
.
new
(
'changelog'
)])
expect
(
repository
.
changelog
.
name
).
to
eq
(
'changelog'
)
expect
(
repository
.
changelog
.
path
).
to
eq
(
'changelog'
)
end
it
'accepts news instead of changelog'
do
expect
(
repository
.
tree
).
to
receive
(
:blobs
).
and_return
([
TestBlob
.
new
(
'news'
)])
expect
(
repository
.
changelog
.
name
).
to
eq
(
'news'
)
expect
(
repository
.
changelog
.
path
).
to
eq
(
'news'
)
end
it
'accepts history instead of changelog'
do
expect
(
repository
.
tree
).
to
receive
(
:blobs
).
and_return
([
TestBlob
.
new
(
'history'
)])
expect
(
repository
.
changelog
.
name
).
to
eq
(
'history'
)
expect
(
repository
.
changelog
.
path
).
to
eq
(
'history'
)
end
it
'accepts changes instead of changelog'
do
expect
(
repository
.
tree
).
to
receive
(
:blobs
).
and_return
([
TestBlob
.
new
(
'changes'
)])
expect
(
repository
.
changelog
.
name
).
to
eq
(
'changes'
)
expect
(
repository
.
changelog
.
path
).
to
eq
(
'changes'
)
end
it
'is case-insensitive'
do
expect
(
repository
.
tree
).
to
receive
(
:blobs
).
and_return
([
TestBlob
.
new
(
'CHANGELOG'
)])
expect
(
repository
.
changelog
.
name
).
to
eq
(
'CHANGELOG'
)
expect
(
repository
.
changelog
.
path
).
to
eq
(
'CHANGELOG'
)
end
end
...
...
@@ -624,7 +624,7 @@ describe Repository, models: true do
repository
.
create_file
(
user
,
'LICENSE'
,
'Copyright!'
,
message:
'Add LICENSE'
,
branch_name:
'master'
)
expect
(
repository
.
license_blob
.
name
).
to
eq
(
'LICENSE'
)
expect
(
repository
.
license_blob
.
path
).
to
eq
(
'LICENSE'
)
end
%w[LICENSE LICENCE LiCensE LICENSE.md LICENSE.foo COPYING COPYING.md]
.
each
do
|
filename
|
...
...
@@ -654,7 +654,7 @@ describe Repository, models: true do
expect
(
repository
.
license_key
).
to
be_nil
end
it
'
detects license file with no recognizable open-source license content
'
do
it
'
returns nil when the content is not recognizable
'
do
repository
.
create_file
(
user
,
'LICENSE'
,
'Copyright!'
,
message:
'Add LICENSE'
,
branch_name:
'master'
)
...
...
@@ -670,12 +670,45 @@ describe Repository, models: true do
end
end
describe
'#license'
do
before
do
repository
.
delete_file
(
user
,
'LICENSE'
,
message:
'Remove LICENSE'
,
branch_name:
'master'
)
end
it
'returns nil when no license is detected'
do
expect
(
repository
.
license
).
to
be_nil
end
it
'returns nil when the repository does not exist'
do
expect
(
repository
).
to
receive
(
:exists?
).
and_return
(
false
)
expect
(
repository
.
license
).
to
be_nil
end
it
'returns nil when the content is not recognizable'
do
repository
.
create_file
(
user
,
'LICENSE'
,
'Copyright!'
,
message:
'Add LICENSE'
,
branch_name:
'master'
)
expect
(
repository
.
license
).
to
be_nil
end
it
'returns the license'
do
license
=
Licensee
::
License
.
new
(
'mit'
)
repository
.
create_file
(
user
,
'LICENSE'
,
license
.
content
,
message:
'Add LICENSE'
,
branch_name:
'master'
)
expect
(
repository
.
license
).
to
eq
(
license
)
end
end
describe
"#gitlab_ci_yml"
,
caching:
true
do
it
'returns valid file'
do
files
=
[
TestBlob
.
new
(
'file'
),
TestBlob
.
new
(
'.gitlab-ci.yml'
),
TestBlob
.
new
(
'copying'
)]
expect
(
repository
.
tree
).
to
receive
(
:blobs
).
and_return
(
files
)
expect
(
repository
.
gitlab_ci_yml
.
name
).
to
eq
(
'.gitlab-ci.yml'
)
expect
(
repository
.
gitlab_ci_yml
.
path
).
to
eq
(
'.gitlab-ci.yml'
)
end
it
'returns nil if not exists'
do
...
...
spec/views/projects/blob/_viewer.html.haml_spec.rb
View file @
08706f68
...
...
@@ -47,10 +47,10 @@ describe 'projects/blob/_viewer.html.haml', :view do
expect
(
rendered
).
to
have_css
(
'.blob-viewer[data-url]'
)
end
it
'
displays a spinne
r'
do
it
'
renders the loading indicato
r'
do
render_view
expect
(
rendered
).
to
have_css
(
'i[aria-label="Loading content"]
'
)
expect
(
view
).
to
render_template
(
'projects/blob/viewers/_loading
'
)
end
end
...
...
Write
Preview
Markdown
is supported
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