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
047b2c1e821a
Commit
ae134175
authored
Apr 02, 2021
by
Georges Racinet
🦑
Browse files
Merged upstream v13.10.2 into release branch
--HG-- branch : heptapod-0-21
parents
c3732f77de8a
beebec95fab2
Pipeline
#20158
passed with stages
in 21 minutes and 39 seconds
Changes
50
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
CHANGELOG.md
View file @
047b2c1e
...
...
@@ -2,6 +2,39 @@
documentation
](
doc/development/changelog.md
)
for instructions on adding your own
entry.
## 13.10.2 (2021-04-01)
### Fixed (1 change)
-
Fixed rendering of the image blobs. !57479
### Added (1 change)
-
Improve performance for composer v2 clients. !55169
## 13.10.1 (2021-03-31)
### Security (6 changes)
-
Leave pool repository on fork unlinking.
-
Fixed XSS in merge requests sidebar.
-
Fix arbitrary read/write in AsciiDoctor and Kroki gems.
-
Prevent infinite loop when checking if collaboration is allowed.
-
Disable arbitrary URI and file reads in JSON validator.
-
Require POST request to trigger system hooks.
### Removed (1 change)
-
Make HipChat project service do nothing. !57434
### Other (3 changes)
-
Remove direct mimemagic dependency. !57387
-
Refactor MimeMagic calls to new MimeType class. !57421
-
Switch to using a fake mimemagic gem. !57443
## 13.10.0 (2021-03-22)
### Security (3 changes)
...
...
GITALY_SERVER_VERSION
View file @
047b2c1e
13.10.0
\ No newline at end of file
13.10.2
\ No newline at end of file
VERSION
View file @
047b2c1e
13.10.0
\ No newline at end of file
13.10.2
\ No newline at end of file
app/assets/javascripts/emoji/components/category.vue
View file @
047b2c1e
<
script
>
import
{
GlIntersectionObserver
}
from
'
@gitlab/ui
'
;
import
{
capitalizeFirstCharacter
}
from
'
~/lib/utils/text_utility
'
;
import
{
humanize
}
from
'
~/lib/utils/text_utility
'
;
import
EmojiGroup
from
'
./emoji_group.vue
'
;
export
default
{
...
...
@@ -25,7 +25,7 @@ export default {
},
computed
:
{
categoryTitle
()
{
return
capitalizeFirstCharacter
(
this
.
category
);
return
humanize
(
this
.
category
);
},
},
methods
:
{
...
...
@@ -33,9 +33,6 @@ export default {
this
.
renderGroup
=
true
;
this
.
$emit
(
'
appear
'
,
this
.
category
);
},
categoryDissappeared
()
{
this
.
renderGroup
=
false
;
},
},
};
</
script
>
...
...
app/assets/javascripts/emoji/components/picker.vue
View file @
047b2c1e
<
script
>
import
{
GlIcon
,
GlDropdown
,
GlSearchBoxByType
}
from
'
@gitlab/ui
'
;
import
{
findLastIndex
}
from
'
lodash
'
;
import
VirtualList
from
'
vue-virtual-scroll-list
'
;
import
{
CATEGORY_NAMES
}
from
'
~/emoji
'
;
import
{
CATEGORY_ICON_MAP
}
from
'
../constants
'
;
import
{
CATEGORY_ICON_MAP
,
FREQUENTLY_USED_KEY
}
from
'
../constants
'
;
import
Category
from
'
./category.vue
'
;
import
EmojiList
from
'
./emoji_list.vue
'
;
import
{
getEmojiCategorie
s
}
from
'
./utils
'
;
import
{
addToFrequentlyUsed
,
getEmojiCategories
,
hasFrequentlyUsedEmoji
s
}
from
'
./utils
'
;
export
default
{
components
:
{
...
...
@@ -25,13 +26,16 @@ export default {
},
data
()
{
return
{
currentCategory
:
null
,
currentCategory
:
0
,
searchValue
:
''
,
};
},
computed
:
{
categoryNames
()
{
return
CATEGORY_NAMES
.
map
((
category
)
=>
({
return
CATEGORY_NAMES
.
filter
((
c
)
=>
{
if
(
c
===
FREQUENTLY_USED_KEY
)
return
hasFrequentlyUsedEmojis
();
return
true
;
}).
map
((
category
)
=>
({
name
:
category
,
icon
:
CATEGORY_ICON_MAP
[
category
],
}));
...
...
@@ -50,6 +54,7 @@ export default {
selectEmoji
(
name
)
{
this
.
$emit
(
'
click
'
,
name
);
this
.
$refs
.
dropdown
.
hide
();
addToFrequentlyUsed
(
name
);
},
getBoundaryElement
()
{
return
document
.
querySelector
(
'
.content-wrapper
'
)
||
'
scrollParent
'
;
...
...
@@ -58,6 +63,11 @@ export default {
this
.
$refs
.
virtualScoller
.
setScrollTop
(
0
);
this
.
$refs
.
virtualScoller
.
forceRender
();
},
async
onScroll
(
event
,
{
offset
})
{
const
categories
=
await
getEmojiCategories
();
this
.
currentCategory
=
findLastIndex
(
Object
.
values
(
categories
),
({
top
})
=>
offset
>=
top
);
},
},
};
</
script
>
...
...
@@ -86,10 +96,10 @@ export default {
class=
"gl-display-flex gl-mx-5 gl-border-b-solid gl-border-gray-100 gl-border-b-1"
>
<button
v-for=
"category in categoryNames"
v-for=
"
(
category
, index)
in categoryNames"
:key=
"category.name"
:class=
"{
'gl-text-black-normal! emoji-picker-category-active':
category.name
=== currentCategory,
'gl-text-black-normal! emoji-picker-category-active':
index
=== currentCategory,
}"
type=
"button"
class=
"gl-border-0 gl-border-b-2 gl-border-b-solid gl-flex-fill-1 gl-text-gray-300 gl-pt-3 gl-pb-3 gl-bg-transparent emoji-picker-category-tab"
...
...
@@ -100,18 +110,20 @@ export default {
</div>
<emoji-list
:search-value=
"searchValue"
>
<
template
#default=
"{ filteredCategories }"
>
<virtual-list
ref=
"virtualScoller"
:size=
"258"
:remain=
"1"
:bench=
"2"
variable
>
<virtual-list
ref=
"virtualScoller"
:size=
"258"
:remain=
"1"
:bench=
"2"
variable
:onscroll=
"onScroll"
>
<div
v-for=
"(category, categoryKey) in filteredCategories"
:key=
"categoryKey"
:style=
"
{ height: category.height + 'px' }"
>
<category
:category=
"categoryKey"
:emojis=
"category.emojis"
@
appear=
"categoryAppeared"
@
click=
"selectEmoji"
/>
<category
:category=
"categoryKey"
:emojis=
"category.emojis"
@
click=
"selectEmoji"
/>
</div>
</virtual-list>
</
template
>
...
...
app/assets/javascripts/emoji/components/utils.js
View file @
047b2c1e
import
{
chunk
,
memoize
}
from
'
lodash
'
;
import
Cookies
from
'
js-cookie
'
;
import
{
chunk
,
memoize
,
uniq
}
from
'
lodash
'
;
import
{
initEmojiMap
,
getEmojiCategoryMap
}
from
'
~/emoji
'
;
import
{
EMOJIS_PER_ROW
,
EMOJI_ROW_HEIGHT
,
CATEGORY_ROW_HEIGHT
}
from
'
../constants
'
;
import
{
EMOJIS_PER_ROW
,
EMOJI_ROW_HEIGHT
,
CATEGORY_ROW_HEIGHT
,
FREQUENTLY_USED_KEY
,
FREQUENTLY_USED_COOKIE_KEY
,
}
from
'
../constants
'
;
export
const
generateCategoryHeight
=
(
emojisLength
)
=>
emojisLength
*
EMOJI_ROW_HEIGHT
+
CATEGORY_ROW_HEIGHT
;
export
const
getFrequentlyUsedEmojis
=
()
=>
{
const
savedEmojis
=
Cookies
.
get
(
FREQUENTLY_USED_COOKIE_KEY
);
if
(
!
savedEmojis
)
return
null
;
const
emojis
=
chunk
(
uniq
(
savedEmojis
.
split
(
'
,
'
)),
9
);
return
{
frequently_used
:
{
emojis
,
top
:
0
,
height
:
generateCategoryHeight
(
emojis
.
length
),
},
};
};
export
const
addToFrequentlyUsed
=
(
emoji
)
=>
{
const
frequentlyUsedEmojis
=
uniq
(
(
Cookies
.
get
(
FREQUENTLY_USED_COOKIE_KEY
)
||
''
)
.
split
(
'
,
'
)
.
filter
((
e
)
=>
e
)
.
concat
(
emoji
),
);
Cookies
.
set
(
FREQUENTLY_USED_COOKIE_KEY
,
frequentlyUsedEmojis
.
join
(
'
,
'
),
{
expires
:
365
});
};
export
const
hasFrequentlyUsedEmojis
=
()
=>
getFrequentlyUsedEmojis
()
!==
null
;
export
const
getEmojiCategories
=
memoize
(
async
()
=>
{
await
initEmojiMap
();
const
categories
=
await
getEmojiCategoryMap
();
let
top
=
0
;
const
frequentlyUsedEmojis
=
getFrequentlyUsedEmojis
();
let
top
=
frequentlyUsedEmojis
?
frequentlyUsedEmojis
.
frequently_used
.
top
+
frequentlyUsedEmojis
.
frequently_used
.
height
:
0
;
return
Object
.
freeze
(
Object
.
keys
(
categories
).
reduce
((
acc
,
category
)
=>
{
const
emojis
=
chunk
(
categories
[
category
],
EMOJIS_PER_ROW
);
const
height
=
generateCategoryHeight
(
emojis
.
length
);
const
newAcc
=
{
...
acc
,
[
category
]:
{
emojis
,
height
,
top
},
};
top
+=
height
;
return
newAcc
;
},
{}),
Object
.
keys
(
categories
)
.
filter
((
c
)
=>
c
!==
FREQUENTLY_USED_KEY
)
.
reduce
((
acc
,
category
)
=>
{
const
emojis
=
chunk
(
categories
[
category
],
EMOJIS_PER_ROW
);
const
height
=
generateCategoryHeight
(
emojis
.
length
);
const
newAcc
=
{
...
acc
,
[
category
]:
{
emojis
,
height
,
top
},
};
top
+=
height
;
return
newAcc
;
},
frequentlyUsedEmojis
||
{}),
);
});
app/assets/javascripts/emoji/constants.js
View file @
047b2c1e
export
const
FREQUENTLY_USED_KEY
=
'
frequently_used
'
;
export
const
FREQUENTLY_USED_COOKIE_KEY
=
'
frequently_used_emojis
'
;
export
const
CATEGORY_ICON_MAP
=
{
[
FREQUENTLY_USED_KEY
]:
'
history
'
,
activity
:
'
dumbbell
'
,
people
:
'
smiley
'
,
nature
:
'
nature
'
,
...
...
app/assets/javascripts/emoji/index.js
View file @
047b2c1e
...
...
@@ -2,7 +2,7 @@ import { escape, minBy } from 'lodash';
import
emojiAliases
from
'
emojis/aliases.json
'
;
import
AccessorUtilities
from
'
../lib/utils/accessor
'
;
import
axios
from
'
../lib/utils/axios_utils
'
;
import
{
CATEGORY_ICON_MAP
}
from
'
./constants
'
;
import
{
CATEGORY_ICON_MAP
,
FREQUENTLY_USED_KEY
}
from
'
./constants
'
;
let
emojiMap
=
null
;
let
validEmojiNames
=
null
;
...
...
@@ -162,6 +162,9 @@ let emojiCategoryMap;
export
function
getEmojiCategoryMap
()
{
if
(
!
emojiCategoryMap
)
{
emojiCategoryMap
=
CATEGORY_NAMES
.
reduce
((
acc
,
category
)
=>
{
if
(
category
===
FREQUENTLY_USED_KEY
)
{
return
acc
;
}
return
{
...
acc
,
[
category
]:
[]
};
},
{});
Object
.
keys
(
emojiMap
).
forEach
((
name
)
=>
{
...
...
app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
View file @
047b2c1e
...
...
@@ -3,6 +3,8 @@ import { throttle } from 'lodash';
import
{
numberToHumanSize
}
from
'
~/lib/utils/number_utils
'
;
import
{
encodeSaferUrl
}
from
'
~/lib/utils/url_utility
'
;
const
BLOB_PREFIX
=
'
blob:
'
;
export
default
{
props
:
{
path
:
{
...
...
@@ -45,7 +47,7 @@ export default {
return
this
.
width
&&
this
.
height
;
},
safePath
()
{
return
encodeSaferUrl
(
this
.
path
);
return
this
.
path
.
startsWith
(
BLOB_PREFIX
)
?
this
.
path
:
encodeSaferUrl
(
this
.
path
);
},
},
beforeDestroy
()
{
...
...
app/helpers/commits_helper.rb
View file @
047b2c1e
...
...
@@ -135,6 +135,8 @@ def conditionally_paginate_diff_files(diffs, paginate:, per: Projects::CommitCon
end
def
cherry_pick_projects_data
(
project
)
return
[]
unless
Feature
.
enabled?
(
:pick_into_project
,
project
,
default_enabled: :yaml
)
target_projects
(
project
).
map
do
|
project
|
{
id:
project
.
id
.
to_s
,
...
...
app/models/merge_request.rb
View file @
047b2c1e
...
...
@@ -1374,7 +1374,7 @@ def broken?
end
def
can_be_merged_by?
(
user
)
access
=
::
Gitlab
::
UserAccess
.
new
(
user
,
container:
project
)
access
=
::
Gitlab
::
UserAccess
.
new
(
user
,
container:
project
,
skip_collaboration_check:
skip_collaboration_check
)
# TODO: will have to change when we have non-publishing MRs
# (e.g., targeting topics)
access
.
can_update_branch?
(
target_branch
)
&&
(
!
project
.
mercurial?
||
access
.
hg_can_publish?
)
...
...
app/models/project.rb
View file @
047b2c1e
...
...
@@ -2742,7 +2742,7 @@ def fetch_branch_allows_collaboration(user, branch_name = nil)
# Issue for N+1: https://gitlab.com/gitlab-org/gitlab-foss/issues/49322
Gitlab
::
GitalyClient
.
allow_n_plus_1_calls
do
merge_requests_allowing_collaboration
(
branch_name
).
any?
do
|
merge_request
|
merge_request
.
can_be_merged_by?
(
user
)
merge_request
.
can_be_merged_by?
(
user
,
skip_collaboration_check:
true
)
end
end
end
...
...
app/presenters/packages/composer/packages_presenter.rb
View file @
047b2c1e
...
...
@@ -5,25 +5,35 @@ module Composer
class
PackagesPresenter
include
API
::
Helpers
::
RelatedResourcesHelpers
def
initialize
(
group
,
packages
)
def
initialize
(
group
,
packages
,
is_v2
=
false
)
@group
=
group
@packages
=
packages
@is_v2
=
is_v2
end
def
root
v1_path
=
expose_path
(
api_v4_group___packages_composer_package_name_path
({
id:
@group
.
id
,
package_name:
'%package%$%hash%'
,
format:
'.json'
},
true
))
v2_path
=
expose_path
(
api_v4_group___packages_composer_p2_package_name_path
({
id:
@group
.
id
,
package_name:
'%package%'
,
format:
'.json'
},
true
))
{
index
=
{
'packages'
=>
[],
'metadata-url'
=>
v2_path
}
# if the client is composer v2 then we don't want to
# include the provider_sha since it is computationally expensive
# to compute.
return
index
if
@is_v2
v1_path
=
expose_path
(
api_v4_group___packages_composer_package_name_path
({
id:
@group
.
id
,
package_name:
'%package%$%hash%'
,
format:
'.json'
},
true
))
index
.
merge!
(
'provider-includes'
=>
{
'p/%hash%.json'
=>
{
'sha256'
=>
provider_sha
}
},
'providers-url'
=>
v1_path
,
'metadata-url'
=>
v2_path
}
'providers-url'
=>
v1_path
)
end
def
provider
...
...
app/services/projects/unlink_fork_service.rb
View file @
047b2c1e
...
...
@@ -32,6 +32,8 @@ def execute
if
fork_network
=
@project
.
root_of_fork_network
fork_network
.
update
(
root_project:
nil
,
deleted_root_project_name:
@project
.
full_name
)
end
@project
.
leave_pool_repository
end
# rubocop: disable Cop/InBatches
...
...
app/views/shared/issuable/_sidebar.html.haml
View file @
047b2c1e
...
...
@@ -138,7 +138,7 @@
=
clipboard_button
(
text:
source_branch
,
title:
_
(
'Copy branch name'
),
placement:
"left"
,
boundary:
'viewport'
)
.sidebar-mr-source-branch.hide-collapsed
%span
=
_
(
'Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}'
).
html_safe
%
{
source_branch_open:
"<cite class='ref-name' title='
#{
source_branch
}
'>"
.
html_safe
,
source_branch_close:
"</cite>"
.
html_safe
,
source_branch:
source_branch
}
=
_
(
'Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}'
).
html_safe
%
{
source_branch_open:
"<cite class='ref-name' title='
#{
html_escape
(
source_branch
)
}
'>"
.
html_safe
,
source_branch_close:
"</cite>"
.
html_safe
,
source_branch:
html_escape
(
source_branch
)
}
=
clipboard_button
(
text:
source_branch
,
title:
_
(
'Copy branch name'
),
placement:
"left"
,
boundary:
'viewport'
)
-
if
show_forwarding_email
...
...
changelogs/unreleased/mimemagic_shim.yml
deleted
100644 → 0
View file @
c3732f77
---
title
:
Switch to using a fake mimemagic gem
merge_request
:
57443
author
:
type
:
other
changelogs/unreleased/remove-direct-mimemagic-dependency-minimal.yml
deleted
100644 → 0
View file @
c3732f77
---
title
:
Refactor MimeMagic calls to new MimeType class
merge_request
:
57421
author
:
type
:
other
changelogs/unreleased/remove-direct-mimemagic-dependency.yml
deleted
100644 → 0
View file @
c3732f77
---
title
:
Remove direct mimemagic dependency
merge_request
:
57387
author
:
type
:
other
changelogs/unreleased/remove_hipchat_gem.yml
deleted
100644 → 0
View file @
c3732f77
---
title
:
Make HipChat project service do nothing
merge_request
:
57434
author
:
type
:
removed
config/initializers/asciidoctor_patch.rb
0 → 100644
View file @
047b2c1e
# frozen_string_literal: true
# Ensure that locked attributes can not be changed using a counter.
# TODO: this can be removed once `asciidoctor` gem is > 2.0.12
# and https://github.com/asciidoctor/asciidoctor/issues/3939 is merged
module
Asciidoctor
module
DocumentPatch
def
counter
(
name
,
seed
=
nil
)
return
@parent_document
.
counter
(
name
,
seed
)
if
@parent_document
# rubocop: disable Gitlab/ModuleWithInstanceVariables
unless
attribute_locked?
name
super
end
end
end
end
class
Asciidoctor::Document
prepend
Asciidoctor
::
DocumentPatch
end
Prev
1
2
3
Next
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