Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
5f2a8d5813
commit
48d25238c3
|
@ -3,7 +3,6 @@ import syntaxHighlight from '~/syntax_highlight';
|
|||
import highlightCurrentUser from './highlight_current_user';
|
||||
import { renderKroki } from './render_kroki';
|
||||
import renderMath from './render_math';
|
||||
import renderMermaid from './render_mermaid';
|
||||
import renderSandboxedMermaid from './render_sandboxed_mermaid';
|
||||
import renderMetrics from './render_metrics';
|
||||
|
||||
|
@ -15,11 +14,8 @@ $.fn.renderGFM = function renderGFM() {
|
|||
syntaxHighlight(this.find('.js-syntax-highlight').get());
|
||||
renderKroki(this.find('.js-render-kroki[hidden]').get());
|
||||
renderMath(this.find('.js-render-math'));
|
||||
if (gon.features?.sandboxedMermaid) {
|
||||
renderSandboxedMermaid(this.find('.js-render-mermaid'));
|
||||
} else {
|
||||
renderMermaid(this.find('.js-render-mermaid'));
|
||||
}
|
||||
renderSandboxedMermaid(this.find('.js-render-mermaid'));
|
||||
|
||||
highlightCurrentUser(this.find('.gfm-project_member').get());
|
||||
|
||||
const issuablePopoverElements = this.find('.gfm-issue, .gfm-merge_request').get();
|
||||
|
|
|
@ -47,6 +47,11 @@ export default {
|
|||
required: false,
|
||||
default: true,
|
||||
},
|
||||
overrideCopy: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -106,6 +111,7 @@ export default {
|
|||
:environment-name="blob.environmentFormattedExternalUrl"
|
||||
:environment-path="blob.environmentExternalUrlForRouteMap"
|
||||
:is-empty="isEmpty"
|
||||
:override-copy="overrideCopy"
|
||||
@copy="proxyCopyRequest"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -54,6 +54,11 @@ export default {
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
overrideCopy: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
downloadUrl() {
|
||||
|
@ -63,6 +68,10 @@ export default {
|
|||
return this.activeViewer === RICH_BLOB_VIEWER;
|
||||
},
|
||||
getBlobHashTarget() {
|
||||
if (this.overrideCopy) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return `[data-blob-hash="${this.blobHash}"]`;
|
||||
},
|
||||
showCopyButton() {
|
||||
|
@ -74,6 +83,13 @@ export default {
|
|||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onCopy() {
|
||||
if (this.overrideCopy) {
|
||||
this.$emit('copy');
|
||||
}
|
||||
},
|
||||
},
|
||||
BTN_COPY_CONTENTS_TITLE,
|
||||
BTN_DOWNLOAD_TITLE,
|
||||
BTN_RAW_TITLE,
|
||||
|
@ -94,6 +110,7 @@ export default {
|
|||
category="primary"
|
||||
variant="default"
|
||||
class="js-copy-blob-source-btn"
|
||||
@click="onCopy"
|
||||
/>
|
||||
<gl-button
|
||||
v-if="!isBinary"
|
||||
|
|
|
@ -227,6 +227,9 @@ export default {
|
|||
setForkTarget(target) {
|
||||
this.forkTarget = target;
|
||||
},
|
||||
onCopy() {
|
||||
navigator.clipboard.writeText(this.blobInfo.rawTextBlob);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -242,7 +245,9 @@ export default {
|
|||
:active-viewer-type="viewer.type"
|
||||
:has-render-error="hasRenderError"
|
||||
:show-path="false"
|
||||
:override-copy="glFeatures.highlightJs"
|
||||
@viewer-changed="switchViewer"
|
||||
@copy="onCopy"
|
||||
>
|
||||
<template #actions>
|
||||
<web-ide-link
|
||||
|
|
|
@ -292,12 +292,28 @@
|
|||
padding: 0;
|
||||
|
||||
form {
|
||||
position: sticky;
|
||||
top: 100px;
|
||||
height: calc(100vh - 100px);
|
||||
overflow: auto;
|
||||
--initial-top: calc(#{$header-height} + #{$mr-tabs-height});
|
||||
--top: var(--initial-top);
|
||||
|
||||
@include gl-sticky;
|
||||
@include gl-overflow-auto;
|
||||
|
||||
top: var(--top);
|
||||
height: calc(100vh - var(--top));
|
||||
padding: 0 15px;
|
||||
margin-bottom: -100px;
|
||||
margin-bottom: calc(var(--top) * -1);
|
||||
|
||||
.with-performance-bar & {
|
||||
--top: calc(var(--initial-top) + #{$performance-bar-height});
|
||||
}
|
||||
|
||||
.with-system-header & {
|
||||
--top: calc(var(--initial-top) + #{$system-header-height});
|
||||
}
|
||||
|
||||
.with-performance-bar.with-system-header & {
|
||||
--top: calc(var(--initial-top) + #{$system-header-height} + #{$performance-bar-height});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -401,4 +401,16 @@ to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1709
|
|||
margin-right: $gl-spacing-scale-10;
|
||||
}
|
||||
}
|
||||
|
||||
.gl-lg-w-30p {
|
||||
@include gl-media-breakpoint-up(lg) {
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
|
||||
.gl-lg-w-40p {
|
||||
@include gl-media-breakpoint-up(lg) {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
||||
/* END-#1825 */
|
||||
|
|
|
@ -2166,6 +2166,7 @@ class Project < ApplicationRecord
|
|||
.append(key: 'CI_PROJECT_ID', value: id.to_s)
|
||||
.append(key: 'CI_PROJECT_NAME', value: path)
|
||||
.append(key: 'CI_PROJECT_TITLE', value: title)
|
||||
.append(key: 'CI_PROJECT_DESCRIPTION', value: description)
|
||||
.append(key: 'CI_PROJECT_PATH', value: full_path)
|
||||
.append(key: 'CI_PROJECT_PATH_SLUG', value: full_path_slug)
|
||||
.append(key: 'CI_PROJECT_NAMESPACE', value: namespace.full_path)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
.detail-page-header-body
|
||||
.issuable-meta.gl-display-flex
|
||||
#js-issuable-header-warnings
|
||||
%h1.title.gl-font-size-h-display.gl-my-0.gl-display-inline-block{ data: { qa_selector: 'title_content' } }
|
||||
%h1.title.page-title.gl-font-size-h-display.gl-my-0.gl-display-inline-block{ data: { qa_selector: 'title_content' } }
|
||||
= markdown_field(@merge_request, :title)
|
||||
|
||||
- unless hide_gutter_toggle
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
.detail-page-description.content-block.js-detail-page-description
|
||||
#js-issuable-app{ data: { initial: issuable_initial_data(issuable).to_json, full_path: @project.full_path } }
|
||||
.title-container
|
||||
%h1.title= markdown_field(issuable, :title)
|
||||
%h1.title.page-title.gl-font-size-h-display= markdown_field(issuable, :title)
|
||||
- if issuable.description.present?
|
||||
.description
|
||||
.md= markdown_field(issuable, :description)
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: sandboxed_mermaid
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74414
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/349755
|
||||
milestone: '14.7'
|
||||
type: development
|
||||
group: group::analyzer frontend
|
||||
default_enabled: true
|
|
@ -348,7 +348,7 @@ to support CI/CD data partitioning.
|
|||
|
||||
This strategy should reduce the risk of implementing CI/CD partitioning to
|
||||
acceptable levels. We are also focusing on implementing partitioning for
|
||||
reading only two partitions initially to make it possible to detach zero
|
||||
reading only from two partitions initially to make it possible to detach zero
|
||||
partitions in case of problems in our production environment. Every iteration
|
||||
phase, described below has a revert strategy and before shipping database
|
||||
changes we want to test them in our benchmarking environment.
|
||||
|
@ -357,6 +357,49 @@ The main way of reducing risk in case of this effort is iteration and making
|
|||
things reversible. Shipping changes, described in this document, in a safe and
|
||||
reliable way is our priority.
|
||||
|
||||
As we move forward with the implementation we will need to find even more ways
|
||||
to iterate on the design, support incremental rollouts and have better control
|
||||
over reverting changes in case of something going wrong. It is sometimes
|
||||
challenging to ship database schema changes iteratively, and even more
|
||||
difficult to support incremental rollouts to the production environment. This
|
||||
can, however, be done, it just sometimes requires additional creativity, that
|
||||
we will certainly need here. Some examples of how this could look like:
|
||||
|
||||
### Incremental rollout of partitioned schema
|
||||
|
||||
Once we introduce a first partitioned routing table (presumably
|
||||
`p_ci_pipelines`) and attach its zero partition (`ci_pipelines`), we will need
|
||||
to start interacting with the new routing table, instead of a concrete
|
||||
partition zero. Usually we would override the database table the `Ci::Pipeline`
|
||||
Rails model would use with something like `self.table_name = 'p_ci_pipelines'`.
|
||||
Unfortunately this approach might not support incremental rollout, because
|
||||
`self.table_name` will be read upon application boot up, and later we might be
|
||||
unable revert this change without restarting the application.
|
||||
|
||||
One way of solving this might be introducing `Ci::Partitioned::Pipeline` model,
|
||||
that will inherit from `Ci::Pipeline`. In that model we would set
|
||||
`self.table_name` to `p_ci_pipeline` and return its meta class from
|
||||
`Ci::Pipeline.partitioned` as a scope. This will allow us to use feature flags
|
||||
to route reads from `ci_pipelines` to `p_ci_pipelines` with a simple revert
|
||||
strategy.
|
||||
|
||||
### Incremental experimentation with partitioned reads
|
||||
|
||||
Another example would be related to the time when we decide to attach another
|
||||
partition. The goal of Phase 1 will be have two partitions per partitioned
|
||||
schema / routing table, meaning that for `p_ci_pipelines` we will have
|
||||
`ci_pipelines` attached as partition zero, and a new `ci_pipelines_p1`
|
||||
partition created for new data. All reads from `p_ci_pipelines` will also need
|
||||
to read data from the `p1` partition and we should also iteratively experiment
|
||||
with reads targeting more than one partition, to evaluate performance and
|
||||
overhead of partitioning.
|
||||
|
||||
We can do that by moving _old_ data to `ci_pipelines_m1` (minus 1) partition
|
||||
iteratively. Perhaps we will create `partition_id = 1` and move some really old
|
||||
pipelines there. We can then iteratively migrate data into `m1` partition to
|
||||
measure the impact, performance and increase our confidence before creating a
|
||||
new partition `p1` for _new_ (still not created) data.
|
||||
|
||||
## Iterations
|
||||
|
||||
We want to focus on Phase 1 iteration first. The goal and the main objective of
|
||||
|
|
|
@ -526,6 +526,7 @@ export CI_PROJECT_ID="34"
|
|||
export CI_PROJECT_DIR="/builds/gitlab-org/gitlab-foss"
|
||||
export CI_PROJECT_NAME="gitlab-foss"
|
||||
export CI_PROJECT_TITLE="GitLab FOSS"
|
||||
export CI_PROJECT_DESCRIPTION="GitLab FOSS is a read-only mirror of GitLab, with all proprietary code removed."
|
||||
export CI_PROJECT_NAMESPACE="gitlab-org"
|
||||
export CI_PROJECT_ROOT_NAMESPACE="gitlab-org"
|
||||
export CI_PROJECT_PATH="gitlab-org/gitlab-foss"
|
||||
|
@ -863,6 +864,8 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
|
|||
++ CI_PROJECT_NAME=ci-debug-trace
|
||||
++ export CI_PROJECT_TITLE='GitLab FOSS'
|
||||
++ CI_PROJECT_TITLE='GitLab FOSS'
|
||||
++ export CI_PROJECT_DESCRIPTION='GitLab FOSS is a read-only mirror of GitLab, with all proprietary code removed.'
|
||||
++ CI_PROJECT_DESCRIPTION='GitLab FOSS is a read-only mirror of GitLab, with all proprietary code removed.'
|
||||
++ export CI_PROJECT_PATH=gitlab-examples/ci-debug-trace
|
||||
++ CI_PROJECT_PATH=gitlab-examples/ci-debug-trace
|
||||
++ export CI_PROJECT_PATH_SLUG=gitlab-examples-ci-debug-trace
|
||||
|
|
|
@ -96,6 +96,7 @@ as it can cause the pipeline to behave unexpectedly.
|
|||
| `CI_PROJECT_REPOSITORY_LANGUAGES` | 12.3 | all | A comma-separated, lowercase list of the languages used in the repository. For example `ruby,javascript,html,css`. |
|
||||
| `CI_PROJECT_ROOT_NAMESPACE` | 13.2 | 0.5 | The root project namespace (username or group name) of the job. For example, if `CI_PROJECT_NAMESPACE` is `root-group/child-group/grandchild-group`, `CI_PROJECT_ROOT_NAMESPACE` is `root-group`. |
|
||||
| `CI_PROJECT_TITLE` | 12.4 | all | The human-readable project name as displayed in the GitLab web interface. |
|
||||
| `CI_PROJECT_DESCRIPTION` | 15.1 | all | The project description as displayed in the GitLab web interface. |
|
||||
| `CI_PROJECT_URL` | 8.10 | 0.5 | The HTTP(S) address of the project. |
|
||||
| `CI_PROJECT_VISIBILITY` | 10.3 | all | The project visibility. Can be `internal`, `private`, or `public`. |
|
||||
| `CI_PROJECT_CLASSIFICATION_LABEL` | 14.2 | all | The project [external authorization classification label](../../user/admin_area/settings/external_authorization.md). |
|
||||
|
|
|
@ -100,27 +100,31 @@ class a {
|
|||
|
||||
## Converting Strings to Integers
|
||||
|
||||
When converting strings to integers, `parseInt` has a slight performance advantage over `Number`, but `Number` is semantic and can be more readable. Prefer `parseInt`, but do not discourage `Number` if it significantly helps readability.
|
||||
When converting strings to integers, `Number` is semantic and can be more readable. Both are allowable, but `Number` has a slight maintainability advantage.
|
||||
|
||||
**WARNING:** `parseInt` **must** include the [radix argument](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt).
|
||||
|
||||
```javascript
|
||||
// bad
|
||||
// bad (missing radix argument)
|
||||
parseInt('10');
|
||||
|
||||
// bad
|
||||
things.map(parseInt)
|
||||
|
||||
// ok
|
||||
Number("106")
|
||||
// good
|
||||
parseInt("106", 10);
|
||||
|
||||
// good
|
||||
things.map(Number)
|
||||
|
||||
// good
|
||||
parseInt("106", 10)
|
||||
Number("106");
|
||||
```
|
||||
|
||||
```javascript
|
||||
// bad (missing radix argument)
|
||||
things.map(parseInt);
|
||||
|
||||
// good
|
||||
things.map(Number);
|
||||
```
|
||||
|
||||
**PLEASE NOTE:** If the String could represent a non-integer (i.e., it includes a decimal), **do not** use `parseInt`. Consider `Number` or `parseFloat` instead.
|
||||
|
||||
## CSS Selectors - Use `js-` prefix
|
||||
|
||||
If a CSS class is only being used in JavaScript as a reference to the element, prefix
|
||||
|
|
|
@ -37,7 +37,7 @@ flowchart LR
|
|||
subgraph backend
|
||||
be["Backend code"]--tested with-->rspec
|
||||
end
|
||||
|
||||
|
||||
be--generates-->fixtures["frontend fixtures"]
|
||||
fixtures--used in-->jest
|
||||
```
|
||||
|
@ -277,16 +277,6 @@ In the event of an emergency, or false positive from this job, add the
|
|||
`pipeline:skip-undercoverage` label to the merge request to allow this job to
|
||||
fail.
|
||||
|
||||
You can disable the `undercover` code coverage check by wrapping the desired block of code in `# :nocov:` lines:
|
||||
|
||||
```ruby
|
||||
# :nocov:
|
||||
def some_method
|
||||
# code coverage for this method will be skipped
|
||||
end
|
||||
# :nocov:
|
||||
```
|
||||
|
||||
## PostgreSQL versions testing
|
||||
|
||||
Our test suite runs against PG12 as GitLab.com runs on PG12 and
|
||||
|
|
|
@ -55,7 +55,6 @@ module Gitlab
|
|||
push_frontend_feature_flag(:security_auto_fix)
|
||||
push_frontend_feature_flag(:new_header_search)
|
||||
push_frontend_feature_flag(:bootstrap_confirmation_modals)
|
||||
push_frontend_feature_flag(:sandboxed_mermaid)
|
||||
push_frontend_feature_flag(:source_editor_toolbar)
|
||||
push_frontend_feature_flag(:gl_avatar_for_all_user_avatars)
|
||||
push_frontend_feature_flag(:mr_attention_requests, current_user)
|
||||
|
|
|
@ -10,7 +10,6 @@ RSpec.describe "User comments on issue", :js do
|
|||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(sandboxed_mermaid: false)
|
||||
project.add_guest(user)
|
||||
sign_in(user)
|
||||
|
||||
|
@ -42,17 +41,6 @@ RSpec.describe "User comments on issue", :js do
|
|||
expect(page.find('pre code').text).to eq code_block_content
|
||||
end
|
||||
|
||||
it "renders HTML content as text in Mermaid" do
|
||||
html_content = "<img onerror=location=`javascript\\u003aalert\\u0028document.domain\\u0029` src=x>"
|
||||
mermaid_content = "graph LR\n B-->D(#{html_content});"
|
||||
comment = "```mermaid\n#{mermaid_content}\n```"
|
||||
|
||||
add_note(comment)
|
||||
|
||||
expect(page.find('svg.mermaid')).not_to have_content 'javascript'
|
||||
within('svg.mermaid') { expect(page).not_to have_selector('img') }
|
||||
end
|
||||
|
||||
it 'opens autocomplete menu for quick actions and have `/label` first choice' do
|
||||
project.add_maintainer(user)
|
||||
create(:label, project: project, title: 'label')
|
||||
|
|
|
@ -1,361 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Mermaid rendering', :js do
|
||||
let_it_be(:project) { create(:project, :public) }
|
||||
|
||||
let(:is_mac) { page.evaluate_script('navigator.platform').include?('Mac') }
|
||||
let(:modifier_key) { is_mac ? :command : :control }
|
||||
|
||||
before do
|
||||
stub_feature_flags(sandboxed_mermaid: false)
|
||||
end
|
||||
|
||||
it 'renders Mermaid diagrams correctly' do
|
||||
description = <<~MERMAID
|
||||
```mermaid
|
||||
graph TD;
|
||||
A-->B;
|
||||
A-->C;
|
||||
B-->D;
|
||||
C-->D;
|
||||
```
|
||||
MERMAID
|
||||
|
||||
issue = create(:issue, project: project, description: description)
|
||||
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
wait_for_requests
|
||||
wait_for_mermaid
|
||||
|
||||
%w[A B C D].each do |label|
|
||||
expect(page).to have_selector('svg text', text: label)
|
||||
end
|
||||
end
|
||||
|
||||
it 'renders linebreaks in Mermaid diagrams' do
|
||||
description = <<~MERMAID
|
||||
```mermaid
|
||||
graph TD;
|
||||
A(Line 1<br>Line 2)-->B(Line 1<br/>Line 2);
|
||||
C(Line 1<br />Line 2)-->D(Line 1<br />Line 2);
|
||||
```
|
||||
MERMAID
|
||||
|
||||
issue = create(:issue, project: project, description: description)
|
||||
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
wait_for_requests
|
||||
wait_for_mermaid
|
||||
|
||||
# From # From https://github.com/mermaid-js/mermaid/blob/170ed89e9ef3e33dc84f8656eed1725379d505df/src/dagre-wrapper/createLabel.js#L39-L42
|
||||
expected = %(<div style="display: inline-block; white-space: nowrap;" xmlns="http://www.w3.org/1999/xhtml">Line 1<br>Line 2</div>)
|
||||
expect(page.html.scan(expected).count).to be(4)
|
||||
end
|
||||
|
||||
it 'does not allow XSS in HTML labels' do
|
||||
description = <<~MERMAID
|
||||
```mermaid
|
||||
graph LR;
|
||||
A-->CLICK_HERE_AND_GET_BONUS;
|
||||
click A alert "aaa"
|
||||
click CLICK_HERE_AND_GET_BONUS "javascript:alert%28%64%6f%63%75%6d%65%6e%74%2e%64%6f%6d%61%69%6e%29" "Here is the XSS"
|
||||
```
|
||||
MERMAID
|
||||
|
||||
issue = create(:issue, project: project, description: description)
|
||||
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
wait_for_requests
|
||||
wait_for_mermaid
|
||||
|
||||
# From https://github.com/mermaid-js/mermaid/blob/170ed89e9ef3e33dc84f8656eed1725379d505df/src/dagre-wrapper/createLabel.js#L39-L42
|
||||
expected = %(<div style="display: inline-block; white-space: nowrap;" xmlns="http://www.w3.org/1999/xhtml">CLICK_HERE_AND_GET_BONUS</div>)
|
||||
expect(page.html).to include(expected)
|
||||
end
|
||||
|
||||
it 'renders only 2 Mermaid blocks and', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/234081' do
|
||||
description = <<~MERMAID
|
||||
```mermaid
|
||||
graph LR
|
||||
A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;
|
||||
```
|
||||
```mermaid
|
||||
graph LR
|
||||
A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;
|
||||
```
|
||||
```mermaid
|
||||
graph LR
|
||||
A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;B-->A;A-->B;
|
||||
```
|
||||
MERMAID
|
||||
|
||||
issue = create(:issue, project: project, description: description)
|
||||
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
wait_for_requests
|
||||
wait_for_mermaid
|
||||
|
||||
page.within('.description') do
|
||||
expect(page).to have_selector('svg')
|
||||
expect(page).to have_selector('pre.mermaid')
|
||||
end
|
||||
end
|
||||
|
||||
it 'correctly sizes mermaid diagram inside <details> block' do
|
||||
description = <<~MERMAID
|
||||
<details>
|
||||
<summary>Click to show diagram</summary>
|
||||
|
||||
```mermaid
|
||||
graph TD;
|
||||
A-->B;
|
||||
A-->C;
|
||||
B-->D;
|
||||
C-->D;
|
||||
```
|
||||
|
||||
</details>
|
||||
MERMAID
|
||||
|
||||
issue = create(:issue, project: project, description: description)
|
||||
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
wait_for_requests
|
||||
wait_for_mermaid
|
||||
|
||||
page.within('.description') do
|
||||
page.find('summary').click
|
||||
svg = page.find('svg.mermaid')
|
||||
|
||||
expect(svg[:style]).to match(/max-width/)
|
||||
expect(svg[:width].to_i).to eq(100)
|
||||
expect(svg[:height].to_i).to be_within(5).of(236)
|
||||
end
|
||||
end
|
||||
|
||||
it 'renders V2 state diagrams' do
|
||||
description = <<~MERMAID
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Idle
|
||||
Idle --> Active : CONTINUE
|
||||
state Active {
|
||||
[*] --> Run
|
||||
Run--> Stop: CONTINUE
|
||||
Stop--> Run: CONTINUE
|
||||
|
||||
Run: Run
|
||||
Run: entry/start
|
||||
Run: check
|
||||
}
|
||||
```
|
||||
MERMAID
|
||||
|
||||
issue = create(:issue, project: project, description: description)
|
||||
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
wait_for_requests
|
||||
wait_for_mermaid
|
||||
|
||||
page.within('.description') do
|
||||
expect(page).to have_selector('svg')
|
||||
end
|
||||
end
|
||||
|
||||
it 'correctly sizes mermaid diagram block' do
|
||||
description = <<~MERMAID
|
||||
```mermaid
|
||||
graph TD;
|
||||
A-->B;
|
||||
A-->C;
|
||||
B-->D;
|
||||
C-->D;
|
||||
```
|
||||
MERMAID
|
||||
|
||||
issue = create(:issue, project: project, description: description)
|
||||
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
wait_for_requests
|
||||
wait_for_mermaid
|
||||
|
||||
expect(page).to have_css('svg.mermaid[style*="max-width"][width="100%"]')
|
||||
end
|
||||
|
||||
it 'display button when diagram exceeds length', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/287806' do
|
||||
graph_edges = "A-->B;B-->A;" * 420
|
||||
|
||||
description = <<~MERMAID
|
||||
```mermaid
|
||||
graph LR
|
||||
#{graph_edges}
|
||||
```
|
||||
MERMAID
|
||||
|
||||
issue = create(:issue, project: project, description: description)
|
||||
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
page.within('.description') do
|
||||
expect(page).not_to have_selector('svg')
|
||||
|
||||
expect(page).to have_selector('pre.mermaid')
|
||||
|
||||
expect(page).to have_selector('.lazy-alert-shown')
|
||||
|
||||
expect(page).to have_selector('.js-lazy-render-mermaid-container')
|
||||
end
|
||||
|
||||
wait_for_requests
|
||||
wait_for_mermaid
|
||||
|
||||
find('.js-lazy-render-mermaid').click
|
||||
|
||||
page.within('.description') do
|
||||
expect(page).to have_selector('svg')
|
||||
|
||||
expect(page).not_to have_selector('.js-lazy-render-mermaid-container')
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not render more than 50 mermaid blocks', :js, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/234081' } do
|
||||
graph_edges = "A-->B;B-->A;"
|
||||
|
||||
description = <<~MERMAID
|
||||
```mermaid
|
||||
graph LR
|
||||
#{graph_edges}
|
||||
```
|
||||
MERMAID
|
||||
|
||||
description *= 51
|
||||
|
||||
issue = create(:issue, project: project, description: description)
|
||||
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
wait_for_requests
|
||||
wait_for_mermaid
|
||||
|
||||
page.within('.description') do
|
||||
expect(page).to have_selector('svg')
|
||||
|
||||
expect(page).to have_selector('.lazy-alert-shown')
|
||||
|
||||
expect(page).to have_selector('.js-lazy-render-mermaid-container')
|
||||
end
|
||||
end
|
||||
|
||||
it 'renders without any limits on wiki page', :js do
|
||||
graph_edges = "A-->B;B-->A;"
|
||||
|
||||
description = <<~MERMAID
|
||||
```mermaid
|
||||
graph LR
|
||||
#{graph_edges}
|
||||
```
|
||||
MERMAID
|
||||
|
||||
description *= 51
|
||||
|
||||
wiki_page = build(:wiki_page, { container: project, content: description })
|
||||
wiki_page.create message: 'mermaid test commit' # rubocop:disable Rails/SaveBang
|
||||
wiki_page = project.wiki.find_page(wiki_page.slug)
|
||||
|
||||
visit project_wiki_path(project, wiki_page)
|
||||
|
||||
wait_for_requests
|
||||
wait_for_mermaid
|
||||
|
||||
page.within('.js-wiki-page-content') do
|
||||
expect(page).not_to have_selector('.lazy-alert-shown')
|
||||
|
||||
expect(page).not_to have_selector('.js-lazy-render-mermaid-container')
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not allow HTML injection' do
|
||||
description = <<~MERMAID
|
||||
```mermaid
|
||||
%%{init: {"flowchart": {"htmlLabels": "false"}} }%%
|
||||
flowchart
|
||||
A["<iframe></iframe>"]
|
||||
```
|
||||
MERMAID
|
||||
|
||||
issue = create(:issue, project: project, description: description)
|
||||
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
wait_for_requests
|
||||
wait_for_mermaid
|
||||
|
||||
page.within('.description') do
|
||||
expect(page).not_to have_xpath("//iframe")
|
||||
end
|
||||
end
|
||||
|
||||
it 'correctly copies and pastes to/from the clipboard' do
|
||||
stub_feature_flags(sandboxed_mermaid: true)
|
||||
|
||||
description = <<~MERMAID
|
||||
```mermaid
|
||||
graph TD;
|
||||
A-->B;
|
||||
A-->C;
|
||||
```
|
||||
MERMAID
|
||||
|
||||
issue = create(:issue, project: project, description: description)
|
||||
|
||||
user = create(:user)
|
||||
sign_in(user)
|
||||
visit project_issue_path(project, issue)
|
||||
|
||||
wait_for_requests
|
||||
wait_for_mermaid
|
||||
|
||||
find('pre.language-mermaid').hover
|
||||
find('copy-code button').click
|
||||
|
||||
sleep 2
|
||||
|
||||
find('#note-body').send_keys [modifier_key, 'v']
|
||||
|
||||
wait_for_requests
|
||||
|
||||
# The codefences do actually get included, but we can't get spec to pass
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83202#note_880621264
|
||||
expect(find('#note-body').value.strip).to eq("graph TD;\n A-->B;\n A-->C;")
|
||||
end
|
||||
end
|
||||
|
||||
def wait_for_mermaid
|
||||
run_idle_callback = <<~RUN_IDLE_CALLBACK
|
||||
window.requestIdleCallback(() => {
|
||||
window.__CAPYBARA_IDLE_CALLBACK_EXEC__ = 1;
|
||||
})
|
||||
RUN_IDLE_CALLBACK
|
||||
|
||||
page.evaluate_script(run_idle_callback)
|
||||
|
||||
Timeout.timeout(Capybara.default_max_wait_time) do
|
||||
loop until finished_rendering?
|
||||
end
|
||||
end
|
||||
|
||||
def finished_rendering?
|
||||
check_idle_callback = <<~CHECK_IDLE_CALLBACK
|
||||
window.__CAPYBARA_IDLE_CALLBACK_EXEC__
|
||||
CHECK_IDLE_CALLBACK
|
||||
page.evaluate_script(check_idle_callback) == 1
|
||||
end
|
|
@ -1,25 +0,0 @@
|
|||
import { initMermaid } from '~/behaviors/markdown/render_mermaid';
|
||||
import * as ColorUtils from '~/lib/utils/color_utils';
|
||||
|
||||
describe('Render mermaid diagrams for Gitlab Flavoured Markdown', () => {
|
||||
it.each`
|
||||
darkMode | expectedTheme
|
||||
${false} | ${'neutral'}
|
||||
${true} | ${'dark'}
|
||||
`('is $darkMode $expectedTheme', async ({ darkMode, expectedTheme }) => {
|
||||
jest.spyOn(ColorUtils, 'darkModeEnabled').mockImplementation(() => darkMode);
|
||||
|
||||
const mermaid = {
|
||||
initialize: jest.fn(),
|
||||
};
|
||||
|
||||
await initMermaid(mermaid);
|
||||
|
||||
expect(mermaid.initialize).toHaveBeenCalledTimes(1);
|
||||
expect(mermaid.initialize).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
theme: expectedTheme,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
|
@ -88,6 +88,14 @@ describe('Blob Header Default Actions', () => {
|
|||
expect(findCopyButton().exists()).toBe(false);
|
||||
expect(findViewRawButton().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('emits a copy event if overrideCopy is set to true', () => {
|
||||
createComponent({ overrideCopy: true });
|
||||
jest.spyOn(wrapper.vm, '$emit');
|
||||
findCopyButton().vm.$emit('click');
|
||||
|
||||
expect(wrapper.vm.$emit).toHaveBeenCalledWith('copy');
|
||||
});
|
||||
});
|
||||
|
||||
describe('view on environment button', () => {
|
||||
|
|
|
@ -163,6 +163,14 @@ describe('Blob content viewer component', () => {
|
|||
expect(findBlobHeader().props('blob')).toEqual(simpleViewerMock);
|
||||
});
|
||||
|
||||
it('copies blob text to clipboard', async () => {
|
||||
jest.spyOn(navigator.clipboard, 'writeText');
|
||||
await createComponent();
|
||||
|
||||
findBlobHeader().vm.$emit('copy');
|
||||
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(simpleViewerMock.rawTextBlob);
|
||||
});
|
||||
|
||||
it('renders a BlobContent component', async () => {
|
||||
await createComponent();
|
||||
|
||||
|
|
|
@ -64,6 +64,8 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
|
|||
value: project.path },
|
||||
{ key: 'CI_PROJECT_TITLE',
|
||||
value: project.title },
|
||||
{ key: 'CI_PROJECT_DESCRIPTION',
|
||||
value: project.description },
|
||||
{ key: 'CI_PROJECT_PATH',
|
||||
value: project.full_path },
|
||||
{ key: 'CI_PROJECT_PATH_SLUG',
|
||||
|
|
|
@ -2809,6 +2809,7 @@ RSpec.describe Ci::Build do
|
|||
{ key: 'CI_PROJECT_ID', value: project.id.to_s, public: true, masked: false },
|
||||
{ key: 'CI_PROJECT_NAME', value: project.path, public: true, masked: false },
|
||||
{ key: 'CI_PROJECT_TITLE', value: project.title, public: true, masked: false },
|
||||
{ key: 'CI_PROJECT_DESCRIPTION', value: project.description, public: true, masked: false },
|
||||
{ key: 'CI_PROJECT_PATH', value: project.full_path, public: true, masked: false },
|
||||
{ key: 'CI_PROJECT_PATH_SLUG', value: project.full_path_slug, public: true, masked: false },
|
||||
{ key: 'CI_PROJECT_NAMESPACE', value: project.namespace.full_path, public: true, masked: false },
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
@ -53,7 +52,7 @@ func (r *Reader) Read(p []byte) (int, error) {
|
|||
chunkLen := int64(binary.BigEndian.Uint32(header[:4]))
|
||||
if chunkType := string(header[4:]); chunkType == "iCCP" {
|
||||
debug("!! iCCP chunk found; skipping")
|
||||
if _, err := io.CopyN(ioutil.Discard, r.underlying, chunkLen+crcLen); err != nil {
|
||||
if _, err := io.CopyN(io.Discard, r.underlying, chunkLen+crcLen); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
continue
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"hash/crc64"
|
||||
"image"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
|
@ -85,9 +84,9 @@ func requireValidImage(t *testing.T, r io.Reader, expected string) {
|
|||
}
|
||||
|
||||
func requireStreamUnchanged(t *testing.T, actual io.Reader, expected io.Reader) {
|
||||
actualBytes, err := ioutil.ReadAll(actual)
|
||||
actualBytes, err := io.ReadAll(actual)
|
||||
require.NoError(t, err)
|
||||
expectedBytes, err := ioutil.ReadAll(expected)
|
||||
expectedBytes, err := io.ReadAll(expected)
|
||||
require.NoError(t, err)
|
||||
|
||||
table := crc64.MakeTable(crc64.ISO)
|
||||
|
|
|
@ -3,7 +3,6 @@ package main
|
|||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
|
@ -24,7 +23,7 @@ func TestDefaultConfig(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestConfigFile(t *testing.T) {
|
||||
f, err := ioutil.TempFile("", "workhorse-config-test")
|
||||
f, err := os.CreateTemp("", "workhorse-config-test")
|
||||
require.NoError(t, err)
|
||||
defer os.Remove(f.Name())
|
||||
|
||||
|
@ -119,7 +118,7 @@ key = "/path/to/private/key"
|
|||
}
|
||||
|
||||
func TestTwoMetricsAddrsAreSpecifiedError(t *testing.T) {
|
||||
f, err := ioutil.TempFile("", "workhorse-config-test")
|
||||
f, err := os.CreateTemp("", "workhorse-config-test")
|
||||
require.NoError(t, err)
|
||||
defer os.Remove(f.Name())
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -651,7 +650,7 @@ func TestGetArchiveProxiedToGitalySuccessfully(t *testing.T) {
|
|||
_, err := os.Stat(tc.archivePath)
|
||||
require.True(t, os.IsNotExist(err), "expected 'does not exist', got: %v", err)
|
||||
} else {
|
||||
cachedArchive, err := ioutil.ReadFile(tc.archivePath)
|
||||
cachedArchive, err := os.ReadFile(tc.archivePath)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBody, string(cachedArchive))
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
@ -46,7 +46,7 @@ func TestBlocker(t *testing.T) {
|
|||
rw.Flush()
|
||||
|
||||
body := rw.Result().Body
|
||||
data, err := ioutil.ReadAll(body)
|
||||
data, err := io.ReadAll(body)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, body.Close())
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"archive/zip"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
|
@ -36,7 +35,7 @@ func testEntryServer(t *testing.T, archive string, entry string) *httptest.Respo
|
|||
}
|
||||
|
||||
func TestDownloadingFromValidArchive(t *testing.T) {
|
||||
tempFile, err := ioutil.TempFile("", "uploads")
|
||||
tempFile, err := os.CreateTemp("", "uploads")
|
||||
require.NoError(t, err)
|
||||
defer tempFile.Close()
|
||||
defer os.Remove(tempFile.Name())
|
||||
|
@ -95,10 +94,9 @@ func TestDownloadingFromValidHTTPArchive(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDownloadingNonExistingFile(t *testing.T) {
|
||||
tempFile, err := ioutil.TempFile("", "uploads")
|
||||
tempFile, err := os.CreateTemp(t.TempDir(), "uploads")
|
||||
require.NoError(t, err)
|
||||
defer tempFile.Close()
|
||||
defer os.Remove(tempFile.Name())
|
||||
|
||||
archive := zip.NewWriter(tempFile)
|
||||
defer archive.Close()
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -60,7 +60,7 @@ func (t *roundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
|
|||
message, contentType = developmentModeResponse(err)
|
||||
}
|
||||
|
||||
injectedResponse.Body = ioutil.NopCloser(strings.NewReader(message))
|
||||
injectedResponse.Body = io.NopCloser(strings.NewReader(message))
|
||||
injectedResponse.Header.Set("Content-Type", contentType)
|
||||
|
||||
return injectedResponse, nil
|
||||
|
|
|
@ -2,7 +2,7 @@ package badgateway
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
|
@ -45,7 +45,7 @@ func TestErrorPage502(t *testing.T) {
|
|||
require.NoError(t, err, "perform roundtrip")
|
||||
defer response.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(response.Body)
|
||||
body, err := io.ReadAll(response.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, tc.contentType, response.Header.Get("content-type"), "content type")
|
||||
|
|
|
@ -7,7 +7,6 @@ package git
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
|
@ -180,7 +179,7 @@ func prepareArchiveTempfile(dir string, prefix string) (*os.File, error) {
|
|||
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ioutil.TempFile(dir, prefix)
|
||||
return os.CreateTemp(dir, prefix)
|
||||
}
|
||||
|
||||
func finalizeCachedArchive(tempFile *os.File, archivePath string) error {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
|
||||
|
@ -40,7 +40,7 @@ func TestParseBasename(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFinalizeArchive(t *testing.T) {
|
||||
tempFile, err := ioutil.TempFile("", "gitlab-workhorse-test")
|
||||
tempFile, err := os.CreateTemp("", "gitlab-workhorse-test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
|
@ -56,7 +55,7 @@ func TestUploadPackTimesOut(t *testing.T) {
|
|||
}
|
||||
defer conn.Close()
|
||||
|
||||
_, _ = io.Copy(ioutil.Discard, conn)
|
||||
_, _ = io.Copy(io.Discard, conn)
|
||||
return &gitalypb.PostUploadPackWithSidechannelResponse{}, nil
|
||||
},
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ package helper
|
|||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"mime"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -197,12 +197,12 @@ func ReadRequestBody(w http.ResponseWriter, r *http.Request, maxBodySize int64)
|
|||
limitedBody := http.MaxBytesReader(w, r.Body, maxBodySize)
|
||||
defer limitedBody.Close()
|
||||
|
||||
return ioutil.ReadAll(limitedBody)
|
||||
return io.ReadAll(limitedBody)
|
||||
}
|
||||
|
||||
func CloneRequestWithNewBody(r *http.Request, body []byte) *http.Request {
|
||||
newReq := *r
|
||||
newReq.Body = ioutil.NopCloser(bytes.NewReader(body))
|
||||
newReq.Body = io.NopCloser(bytes.NewReader(body))
|
||||
newReq.Header = HeaderClone(r.Header)
|
||||
newReq.ContentLength = int64(len(body))
|
||||
return &newReq
|
||||
|
|
|
@ -2,12 +2,11 @@ package helper
|
|||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
func ReadAllTempfile(r io.Reader) (tempfile *os.File, err error) {
|
||||
tempfile, err = ioutil.TempFile("", "gitlab-workhorse-read-all-tempfile")
|
||||
tempfile, err = os.CreateTemp("", "gitlab-workhorse-read-all-tempfile")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package helper
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
@ -131,7 +130,7 @@ func (w *coupledWriter) tempfileWrite(data []byte) (int, error) {
|
|||
}
|
||||
|
||||
func (*coupledWriter) newTempfile() (tempfile *os.File, err error) {
|
||||
tempfile, err = ioutil.TempFile("", "gitlab-workhorse-coupledWriter")
|
||||
tempfile, err = os.CreateTemp("", "gitlab-workhorse-coupledWriter")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"testing/iotest"
|
||||
)
|
||||
|
@ -14,7 +13,7 @@ func TestBusyReader(t *testing.T) {
|
|||
r := testReader(testData)
|
||||
br, _ := NewWriteAfterReader(r, &bytes.Buffer{})
|
||||
|
||||
result, err := ioutil.ReadAll(br)
|
||||
result, err := io.ReadAll(br)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -27,7 +26,7 @@ func TestBusyReader(t *testing.T) {
|
|||
func TestFirstWriteAfterReadDone(t *testing.T) {
|
||||
writeRecorder := &bytes.Buffer{}
|
||||
br, cw := NewWriteAfterReader(&bytes.Buffer{}, writeRecorder)
|
||||
if _, err := io.Copy(ioutil.Discard, br); err != nil {
|
||||
if _, err := io.Copy(io.Discard, br); err != nil {
|
||||
t.Fatalf("copy from busyreader: %v", err)
|
||||
}
|
||||
testData := "test data"
|
||||
|
@ -53,7 +52,7 @@ func TestWriteDelay(t *testing.T) {
|
|||
}
|
||||
|
||||
// Unblock the coupled writer by draining the reader
|
||||
if _, err := io.Copy(ioutil.Discard, br); err != nil {
|
||||
if _, err := io.Copy(io.Discard, br); err != nil {
|
||||
t.Fatalf("copy from busyreader: %v", err)
|
||||
}
|
||||
// Now it is no longer an error if 'w' receives a Write()
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/mitchellh/copystructure"
|
||||
|
@ -148,7 +147,7 @@ func (r *HttpReadSeeker) Seek(offset int64, whence int) (int64, error) {
|
|||
if r.r != nil {
|
||||
// Try to read, which is cheaper than doing a request
|
||||
if r.pos < offset && offset-r.pos <= shortSeekBytes {
|
||||
_, err := io.CopyN(ioutil.Discard, r, offset-r.pos)
|
||||
_, err := io.CopyN(io.Discard, r, offset-r.pos)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package httprs
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
|
@ -49,7 +48,7 @@ type fakeRoundTripper struct {
|
|||
func (f *fakeRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
fw := &fakeResponseWriter{h: http.Header{}}
|
||||
var err error
|
||||
fw.tmp, err = ioutil.TempFile(os.TempDir(), "httprs")
|
||||
fw.tmp, err = os.CreateTemp(os.TempDir(), "httprs")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -79,7 +78,7 @@ type RSFactory func() *HttpReadSeeker
|
|||
|
||||
func newRSFactory(flags int) RSFactory {
|
||||
return func() *HttpReadSeeker {
|
||||
tmp, err := ioutil.TempFile(os.TempDir(), "httprs")
|
||||
tmp, err := os.CreateTemp(os.TempDir(), "httprs")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -113,7 +112,7 @@ func TestHttpWebServer(t *testing.T) {
|
|||
Convey("Scenario: testing WebServer", t, func() {
|
||||
dir := t.TempDir()
|
||||
|
||||
err := ioutil.WriteFile(filepath.Join(dir, "file"), make([]byte, 10000), 0755)
|
||||
err := os.WriteFile(filepath.Join(dir, "file"), make([]byte, 10000), 0755)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(dir)))
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"encoding/json"
|
||||
"image"
|
||||
"image/png"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
|
@ -184,7 +184,7 @@ func TestServeOriginalImageWhenSourceImageFormatIsNotAllowed(t *testing.T) {
|
|||
cfg := config.DefaultImageResizerConfig
|
||||
// SVG images are not allowed to be resized
|
||||
svgImagePath := "../../testdata/image.svg"
|
||||
svgImage, err := ioutil.ReadFile(svgImagePath)
|
||||
svgImage, err := os.ReadFile(svgImagePath)
|
||||
require.NoError(t, err)
|
||||
// ContentType is no longer used to perform the format validation.
|
||||
// To make the test more strict, we'll use allowed, but incorrect ContentType.
|
||||
|
@ -193,7 +193,7 @@ func TestServeOriginalImageWhenSourceImageFormatIsNotAllowed(t *testing.T) {
|
|||
resp := requestScaledImage(t, nil, params, cfg)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
responseData, err := ioutil.ReadAll(resp.Body)
|
||||
responseData, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, svgImage, responseData, "expected original image")
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ func TestServeOriginalImageWhenSourceImageFormatIsNotAllowed(t *testing.T) {
|
|||
func TestServeOriginalImageWhenSourceImageIsTooSmall(t *testing.T) {
|
||||
content := []byte("PNG") // 3 bytes only, invalid as PNG/JPEG image
|
||||
|
||||
img, err := ioutil.TempFile("", "*.png")
|
||||
img, err := os.CreateTemp("", "*.png")
|
||||
require.NoError(t, err)
|
||||
|
||||
defer img.Close()
|
||||
|
@ -216,7 +216,7 @@ func TestServeOriginalImageWhenSourceImageIsTooSmall(t *testing.T) {
|
|||
resp := requestScaledImage(t, nil, params, cfg)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
responseData, err := ioutil.ReadAll(resp.Body)
|
||||
responseData, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, content, responseData, "expected original image")
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package parser
|
|||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
@ -16,7 +15,7 @@ type cache struct {
|
|||
}
|
||||
|
||||
func newCache(tempDir, filename string, data interface{}) (*cache, error) {
|
||||
f, err := ioutil.TempFile(tempDir, filename)
|
||||
f, err := os.CreateTemp(tempDir, filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package parser
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -21,7 +21,7 @@ func TestCache(t *testing.T) {
|
|||
require.NoError(t, cache.SetEntry(1, &c))
|
||||
require.NoError(t, cache.setOffset(0))
|
||||
|
||||
content, err := ioutil.ReadAll(cache.file)
|
||||
content, err := io.ReadAll(cache.file)
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := []byte{0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x2, 0x0}
|
||||
|
|
|
@ -2,7 +2,6 @@ package parser
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
@ -39,7 +38,7 @@ type ResultSetRef struct {
|
|||
func NewHovers(config Config) (*Hovers, error) {
|
||||
tempPath := config.TempPath
|
||||
|
||||
file, err := ioutil.TempFile(tempPath, "hovers")
|
||||
file, err := os.CreateTemp(tempPath, "hovers")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"gitlab.com/gitlab-org/labkit/log"
|
||||
|
@ -33,7 +32,7 @@ func NewParser(ctx context.Context, r io.Reader, config Config) (io.ReadCloser,
|
|||
}
|
||||
|
||||
// ZIP files need to be seekable. Don't hold it all in RAM, use a tempfile
|
||||
tempFile, err := ioutil.TempFile(config.TempPath, Lsif)
|
||||
tempFile, err := os.CreateTemp(config.TempPath, Lsif)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
@ -26,13 +25,13 @@ func TestGenerate(t *testing.T) {
|
|||
}
|
||||
|
||||
func verifyCorrectnessOf(t *testing.T, tmpDir, fileName string) {
|
||||
file, err := ioutil.ReadFile(filepath.Join(tmpDir, fileName))
|
||||
file, err := os.ReadFile(filepath.Join(tmpDir, fileName))
|
||||
require.NoError(t, err)
|
||||
|
||||
var buf bytes.Buffer
|
||||
require.NoError(t, json.Indent(&buf, file, "", " "))
|
||||
|
||||
expected, err := ioutil.ReadFile(filepath.Join("testdata/expected/", fileName))
|
||||
expected, err := os.ReadFile(filepath.Join("testdata/expected/", fileName))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, string(expected), buf.String())
|
||||
|
|
|
@ -3,7 +3,6 @@ package parser
|
|||
import (
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
@ -25,7 +24,7 @@ func BenchmarkGenerate(b *testing.B) {
|
|||
parser, err := NewParser(context.Background(), file, Config{})
|
||||
require.NoError(b, err)
|
||||
|
||||
_, err = io.Copy(ioutil.Discard, parser)
|
||||
_, err = io.Copy(io.Discard, parser)
|
||||
require.NoError(b, err)
|
||||
require.NoError(b, parser.Close())
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ package secret
|
|||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
|
@ -57,7 +57,7 @@ func setBytes() ([]byte, error) {
|
|||
return theSecret.bytes, nil
|
||||
}
|
||||
|
||||
base64Bytes, err := ioutil.ReadFile(theSecret.path)
|
||||
base64Bytes, err := os.ReadFile(theSecret.path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("secret.setBytes: read %q: %v", theSecret.path, err)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package contentprocessor
|
|||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
@ -306,7 +305,7 @@ func makeRequest(t *testing.T, handler http.HandlerFunc, body string, dispositio
|
|||
SetContentHeaders(handler).ServeHTTP(rw, req)
|
||||
|
||||
resp := rw.Result()
|
||||
respBody, err := ioutil.ReadAll(resp.Body)
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, body, string(respBody))
|
||||
|
|
|
@ -2,7 +2,6 @@ package senddata
|
|||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
|
@ -47,7 +46,7 @@ func TestWriter(t *testing.T) {
|
|||
recorder.Flush()
|
||||
|
||||
body := recorder.Result().Body
|
||||
data, err := ioutil.ReadAll(body)
|
||||
data, err := io.ReadAll(body)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, body.Close())
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ package sendfile
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
|
||||
|
@ -128,7 +127,7 @@ func sendFileFromDisk(w http.ResponseWriter, r *http.Request, file string) {
|
|||
countSendFileMetrics(fi.Size(), r)
|
||||
|
||||
if contentTypeHeaderPresent {
|
||||
data, err := ioutil.ReadAll(io.LimitReader(content, headers.MaxDetectSize))
|
||||
data, err := io.ReadAll(io.LimitReader(content, headers.MaxDetectSize))
|
||||
if err != nil {
|
||||
helper.Fail500(w, r, fmt.Errorf("content type detection: %v", err))
|
||||
return
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package sendfile
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -15,7 +16,7 @@ func TestResponseWriter(t *testing.T) {
|
|||
upstreamResponse := "hello world"
|
||||
|
||||
fixturePath := "testdata/sent-file.txt"
|
||||
fixtureContent, err := ioutil.ReadFile(fixturePath)
|
||||
fixtureContent, err := os.ReadFile(fixturePath)
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
|
@ -52,7 +53,7 @@ func TestResponseWriter(t *testing.T) {
|
|||
rw.Flush()
|
||||
|
||||
body := rw.Result().Body
|
||||
data, err := ioutil.ReadAll(body)
|
||||
data, err := io.ReadAll(body)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, body.Close())
|
||||
|
||||
|
@ -90,7 +91,7 @@ func TestSuccessOverrideContentHeadersFeatureEnabled(t *testing.T) {
|
|||
func TestSuccessOverrideContentHeadersRangeRequestFeatureEnabled(t *testing.T) {
|
||||
fixturePath := "../../testdata/forgedfile.png"
|
||||
|
||||
fixtureContent, err := ioutil.ReadFile(fixturePath)
|
||||
fixtureContent, err := os.ReadFile(fixturePath)
|
||||
require.NoError(t, err)
|
||||
|
||||
r, err := http.NewRequest("GET", "/foo", nil)
|
||||
|
@ -113,7 +114,7 @@ func TestSuccessOverrideContentHeadersRangeRequestFeatureEnabled(t *testing.T) {
|
|||
|
||||
resp := rw.Result()
|
||||
body := resp.Body
|
||||
data, err := ioutil.ReadAll(body)
|
||||
data, err := io.ReadAll(body)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, body.Close())
|
||||
|
||||
|
@ -138,7 +139,7 @@ func TestSuccessInlineWhitelistedTypesFeatureEnabled(t *testing.T) {
|
|||
}
|
||||
|
||||
func makeRequest(t *testing.T, fixturePath string, httpHeaders map[string]string) *http.Response {
|
||||
fixtureContent, err := ioutil.ReadFile(fixturePath)
|
||||
fixtureContent, err := os.ReadFile(fixturePath)
|
||||
require.NoError(t, err)
|
||||
|
||||
r, err := http.NewRequest("GET", "/foo", nil)
|
||||
|
@ -161,7 +162,7 @@ func makeRequest(t *testing.T, fixturePath string, httpHeaders map[string]string
|
|||
|
||||
resp := rw.Result()
|
||||
body := resp.Body
|
||||
data, err := ioutil.ReadAll(body)
|
||||
data, err := io.ReadAll(body)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, body.Close())
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package sendurl
|
|||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
|
@ -40,7 +39,7 @@ func testEntryServer(t *testing.T, requestURL string, httpHeaders http.Header, a
|
|||
serveFile := func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, "GET", r.Method)
|
||||
|
||||
tempFile, err := ioutil.TempFile("", "download_file")
|
||||
tempFile, err := os.CreateTemp("", "download_file")
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, os.Remove(tempFile.Name()))
|
||||
defer tempFile.Close()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package staticpages
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
|
||||
|
@ -12,7 +12,7 @@ func (s *Static) DeployPage(handler http.Handler) http.Handler {
|
|||
deployPage := filepath.Join(s.DocumentRoot, "index.html")
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := ioutil.ReadFile(deployPage)
|
||||
data, err := os.ReadFile(deployPage)
|
||||
if err != nil {
|
||||
handler.ServeHTTP(w, r)
|
||||
return
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package staticpages
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
|
@ -31,7 +31,7 @@ func TestIfDeployPageExist(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
|
||||
deployPage := "DEPLOY"
|
||||
ioutil.WriteFile(filepath.Join(dir, "index.html"), []byte(deployPage), 0600)
|
||||
os.WriteFile(filepath.Join(dir, "index.html"), []byte(deployPage), 0600)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ package staticpages
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
@ -97,7 +97,7 @@ func (s *errorPageResponseWriter) writeHTML() (string, []byte) {
|
|||
errorPageFile := filepath.Join(s.path, fmt.Sprintf("%d.html", s.status))
|
||||
|
||||
// check if custom error page exists, serve this page instead
|
||||
if data, err := ioutil.ReadFile(errorPageFile); err == nil {
|
||||
if data, err := os.ReadFile(errorPageFile); err == nil {
|
||||
return "text/html; charset=utf-8", data
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ package staticpages
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
|
@ -17,7 +17,7 @@ func TestIfErrorPageIsPresented(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
|
||||
errorPage := "ERROR"
|
||||
ioutil.WriteFile(filepath.Join(dir, "404.html"), []byte(errorPage), 0600)
|
||||
os.WriteFile(filepath.Join(dir, "404.html"), []byte(errorPage), 0600)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
h := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
|
@ -57,7 +57,7 @@ func TestIfErrorPageIsIgnoredInDevelopment(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
|
||||
errorPage := "ERROR"
|
||||
ioutil.WriteFile(filepath.Join(dir, "500.html"), []byte(errorPage), 0600)
|
||||
os.WriteFile(filepath.Join(dir, "500.html"), []byte(errorPage), 0600)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
serverError := "Interesting Server Error"
|
||||
|
@ -76,7 +76,7 @@ func TestIfErrorPageIsIgnoredIfCustomError(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
|
||||
errorPage := "ERROR"
|
||||
ioutil.WriteFile(filepath.Join(dir, "500.html"), []byte(errorPage), 0600)
|
||||
os.WriteFile(filepath.Join(dir, "500.html"), []byte(errorPage), 0600)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
serverError := "Interesting Server Error"
|
||||
|
@ -107,7 +107,7 @@ func TestErrorPageInterceptedByContentType(t *testing.T) {
|
|||
dir := t.TempDir()
|
||||
|
||||
errorPage := "ERROR"
|
||||
ioutil.WriteFile(filepath.Join(dir, "500.html"), []byte(errorPage), 0600)
|
||||
os.WriteFile(filepath.Join(dir, "500.html"), []byte(errorPage), 0600)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
serverError := "Interesting Server Error"
|
||||
|
|
|
@ -3,9 +3,9 @@ package staticpages
|
|||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
|
@ -64,7 +64,7 @@ func TestServingTheActualFile(t *testing.T) {
|
|||
httpRequest, _ := http.NewRequest("GET", "/file", nil)
|
||||
|
||||
fileContent := "STATIC"
|
||||
ioutil.WriteFile(filepath.Join(dir, "file"), []byte(fileContent), 0600)
|
||||
os.WriteFile(filepath.Join(dir, "file"), []byte(fileContent), 0600)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
st := &Static{DocumentRoot: dir}
|
||||
|
@ -127,8 +127,8 @@ func testServingThePregzippedFile(t *testing.T, enableGzip bool) {
|
|||
fileGzip.Write([]byte(fileContent))
|
||||
fileGzip.Close()
|
||||
|
||||
ioutil.WriteFile(filepath.Join(dir, "file.gz"), fileGzipContent.Bytes(), 0600)
|
||||
ioutil.WriteFile(filepath.Join(dir, "file"), []byte(fileContent), 0600)
|
||||
os.WriteFile(filepath.Join(dir, "file.gz"), fileGzipContent.Bytes(), 0600)
|
||||
os.WriteFile(filepath.Join(dir, "file"), []byte(fileContent), 0600)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
st := &Static{DocumentRoot: dir}
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -49,10 +49,10 @@ var (
|
|||
|
||||
func init() {
|
||||
var err error
|
||||
if GitalyReceivePackResponseMock, err = ioutil.ReadFile(path.Join(RootDir(), "testdata/receive-pack-fixture.txt")); err != nil {
|
||||
if GitalyReceivePackResponseMock, err = os.ReadFile(path.Join(RootDir(), "testdata/receive-pack-fixture.txt")); err != nil {
|
||||
log.WithError(err).Fatal("Unable to read pack response")
|
||||
}
|
||||
if GitalyUploadPackResponseMock, err = ioutil.ReadFile(path.Join(RootDir(), "testdata/upload-pack-fixture.txt")); err != nil {
|
||||
if GitalyUploadPackResponseMock, err = os.ReadFile(path.Join(RootDir(), "testdata/upload-pack-fixture.txt")); err != nil {
|
||||
log.WithError(err).Fatal("Unable to read pack response")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
|
@ -121,7 +120,7 @@ func RootDir() string {
|
|||
|
||||
func LoadFile(t *testing.T, filePath string) string {
|
||||
t.Helper()
|
||||
content, err := ioutil.ReadFile(path.Join(RootDir(), filePath))
|
||||
content, err := os.ReadFile(path.Join(RootDir(), filePath))
|
||||
require.NoError(t, err)
|
||||
return string(content)
|
||||
}
|
||||
|
@ -129,7 +128,7 @@ func LoadFile(t *testing.T, filePath string) string {
|
|||
func ReadAll(t *testing.T, r io.Reader) []byte {
|
||||
t.Helper()
|
||||
|
||||
b, err := ioutil.ReadAll(r)
|
||||
b, err := io.ReadAll(r)
|
||||
require.NoError(t, err)
|
||||
return b
|
||||
}
|
||||
|
@ -176,7 +175,7 @@ func SetupStaticFileHelper(t *testing.T, fpath, content, directory string) strin
|
|||
require.NoError(t, os.MkdirAll(path.Join(absDocumentRoot, path.Dir(fpath)), 0755), "create document root")
|
||||
|
||||
staticFile := path.Join(absDocumentRoot, fpath)
|
||||
require.NoError(t, ioutil.WriteFile(staticFile, []byte(content), 0666), "write file content")
|
||||
require.NoError(t, os.WriteFile(staticFile, []byte(content), 0666), "write file content")
|
||||
|
||||
return absDocumentRoot
|
||||
}
|
||||
|
|
|
@ -6,10 +6,11 @@ import (
|
|||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -58,7 +59,7 @@ func TestUploadHandlerSendingToExternalStorage(t *testing.T) {
|
|||
tempPath := t.TempDir()
|
||||
|
||||
archiveData, md5 := createTestZipArchive(t)
|
||||
archiveFile, err := ioutil.TempFile(tempPath, "artifact.zip")
|
||||
archiveFile, err := os.CreateTemp(tempPath, "artifact.zip")
|
||||
require.NoError(t, err)
|
||||
_, err = archiveFile.Write(archiveData)
|
||||
require.NoError(t, err)
|
||||
|
@ -69,7 +70,7 @@ func TestUploadHandlerSendingToExternalStorage(t *testing.T) {
|
|||
storeServerMux.HandleFunc("/url/put", func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, "PUT", r.Method)
|
||||
|
||||
receivedData, err := ioutil.ReadAll(r.Body)
|
||||
receivedData, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, archiveData, receivedData)
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
@ -72,7 +71,7 @@ func testArtifactsUploadServer(t *testing.T, authResponse *api.Response, bodyPro
|
|||
return
|
||||
}
|
||||
|
||||
_, err := ioutil.ReadFile(r.FormValue("file.path"))
|
||||
_, err := os.ReadFile(r.FormValue("file.path"))
|
||||
if err != nil {
|
||||
t.Fatal("Expected file to be readable")
|
||||
return
|
||||
|
@ -85,7 +84,7 @@ func testArtifactsUploadServer(t *testing.T, authResponse *api.Response, bodyPro
|
|||
}
|
||||
|
||||
if r.FormValue("metadata.path") != "" {
|
||||
metadata, err := ioutil.ReadFile(r.FormValue("metadata.path"))
|
||||
metadata, err := os.ReadFile(r.FormValue("metadata.path"))
|
||||
if err != nil {
|
||||
t.Fatal("Expected metadata to be readable")
|
||||
return
|
||||
|
@ -96,7 +95,7 @@ func testArtifactsUploadServer(t *testing.T, authResponse *api.Response, bodyPro
|
|||
return
|
||||
}
|
||||
defer gz.Close()
|
||||
metadata, err = ioutil.ReadAll(gz)
|
||||
metadata, err = io.ReadAll(gz)
|
||||
if err != nil {
|
||||
t.Fatal("Expected metadata to be valid")
|
||||
return
|
||||
|
|
|
@ -3,7 +3,6 @@ package upload
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -53,9 +52,6 @@ func Artifacts(myAPI *api.API, h http.Handler, p Preparer) http.Handler {
|
|||
}
|
||||
|
||||
func (a *artifactsUploadProcessor) generateMetadataFromZip(ctx context.Context, file *destination.FileHandler) (*destination.FileHandler, error) {
|
||||
metaReader, metaWriter := io.Pipe()
|
||||
defer metaWriter.Close()
|
||||
|
||||
metaOpts := &destination.UploadOpts{
|
||||
LocalTempPath: os.TempDir(),
|
||||
}
|
||||
|
@ -68,24 +64,22 @@ func (a *artifactsUploadProcessor) generateMetadataFromZip(ctx context.Context,
|
|||
zipMd := exec.CommandContext(ctx, "gitlab-zip-metadata", fileName)
|
||||
zipMd.Stderr = log.ContextLogger(ctx).Writer()
|
||||
zipMd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||
zipMd.Stdout = metaWriter
|
||||
|
||||
zipMdOut, err := zipMd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer zipMdOut.Close()
|
||||
|
||||
if err := zipMd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer helper.CleanUpProcessGroup(zipMd)
|
||||
|
||||
type saveResult struct {
|
||||
error
|
||||
*destination.FileHandler
|
||||
fh, err := destination.Upload(ctx, zipMdOut, -1, "metadata.gz", metaOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
done := make(chan saveResult)
|
||||
go func() {
|
||||
var result saveResult
|
||||
result.FileHandler, result.error = destination.Upload(ctx, metaReader, -1, "metadata.gz", metaOpts)
|
||||
|
||||
done <- result
|
||||
}()
|
||||
|
||||
if err := zipMd.Wait(); err != nil {
|
||||
st, ok := helper.ExitStatus(err)
|
||||
|
@ -105,9 +99,7 @@ func (a *artifactsUploadProcessor) generateMetadataFromZip(ctx context.Context,
|
|||
}
|
||||
}
|
||||
|
||||
metaWriter.Close()
|
||||
result := <-done
|
||||
return result.FileHandler, result.error
|
||||
return fh, nil
|
||||
}
|
||||
|
||||
func (a *artifactsUploadProcessor) ProcessFile(ctx context.Context, formName string, file *destination.FileHandler, writer *multipart.Writer) error {
|
||||
|
|
|
@ -2,7 +2,7 @@ package upload
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
@ -42,7 +42,7 @@ func RequestBody(rails PreAuthorizer, h http.Handler, p Preparer) http.Handler {
|
|||
|
||||
// Hijack body
|
||||
body := data.Encode()
|
||||
r.Body = ioutil.NopCloser(strings.NewReader(body))
|
||||
r.Body = io.NopCloser(strings.NewReader(body))
|
||||
r.ContentLength = int64(len(body))
|
||||
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package upload
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
|
@ -32,7 +31,7 @@ func TestRequestBody(t *testing.T) {
|
|||
resp := testUpload(&rails{}, &alwaysLocalPreparer{}, echoProxy(t, fileLen), body)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
uploadEcho, err := ioutil.ReadAll(resp.Body)
|
||||
uploadEcho, err := io.ReadAll(resp.Body)
|
||||
|
||||
require.NoError(t, err, "Can't read response body")
|
||||
require.Equal(t, fileContent, string(uploadEcho))
|
||||
|
@ -44,7 +43,7 @@ func TestRequestBodyCustomPreparer(t *testing.T) {
|
|||
resp := testUpload(&rails{}, &alwaysLocalPreparer{}, echoProxy(t, fileLen), body)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
uploadEcho, err := ioutil.ReadAll(resp.Body)
|
||||
uploadEcho, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err, "Can't read response body")
|
||||
require.Equal(t, fileContent, string(uploadEcho))
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
@ -226,7 +225,7 @@ func (fh *FileHandler) newLocalFile(ctx context.Context, opts *UploadOpts) (cons
|
|||
return nil, fmt.Errorf("newLocalFile: mkdir %q: %v", opts.LocalTempPath, err)
|
||||
}
|
||||
|
||||
file, err := ioutil.TempFile(opts.LocalTempPath, "gitlab-workhorse-upload")
|
||||
file, err := os.CreateTemp(opts.LocalTempPath, "gitlab-workhorse-upload")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("newLocalFile: create file: %v", err)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package filestore
|
|||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -12,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
func TestConsume(t *testing.T) {
|
||||
f, err := ioutil.TempFile("", "filestore-local-file")
|
||||
f, err := os.CreateTemp("", "filestore-local-file")
|
||||
if f != nil {
|
||||
defer os.Remove(f.Name())
|
||||
}
|
||||
|
@ -32,7 +31,7 @@ func TestConsume(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, int64(len(content)), n)
|
||||
|
||||
consumedContent, err := ioutil.ReadFile(f.Name())
|
||||
consumedContent, err := os.ReadFile(f.Name())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, content, string(consumedContent))
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
|
@ -66,7 +65,7 @@ func (m *Multipart) Upload(ctx context.Context, r io.Reader) error {
|
|||
}
|
||||
}
|
||||
|
||||
n, err := io.Copy(ioutil.Discard, r)
|
||||
n, err := io.Copy(io.Discard, r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("drain pipe: %v", err)
|
||||
}
|
||||
|
@ -93,7 +92,7 @@ func (m *Multipart) Delete() {
|
|||
}
|
||||
|
||||
func (m *Multipart) readAndUploadOnePart(ctx context.Context, partURL string, putHeaders map[string]string, src io.Reader, partNumber int) (*completeMultipartUploadPart, error) {
|
||||
file, err := ioutil.TempFile("", "part-buffer")
|
||||
file, err := os.CreateTemp("", "part-buffer")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create temporary buffer file: %v", err)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package objectstore_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
|
@ -22,7 +22,7 @@ func TestMultipartUploadWithUpcaseETags(t *testing.T) {
|
|||
var putCnt, postCnt int
|
||||
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, err := ioutil.ReadAll(r.Body)
|
||||
_, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
defer r.Body.Close()
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"gitlab.com/gitlab-org/labkit/mask"
|
||||
|
@ -53,7 +52,7 @@ func newObject(putURL, deleteURL string, putHeaders map[string]string, size int6
|
|||
|
||||
func (o *Object) Upload(ctx context.Context, r io.Reader) error {
|
||||
// we should prevent pr.Close() otherwise it may shadow error set with pr.CloseWithError(err)
|
||||
req, err := http.NewRequest(http.MethodPut, o.putURL, ioutil.NopCloser(r))
|
||||
req, err := http.NewRequest(http.MethodPut, o.putURL, io.NopCloser(r))
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("PUT %q: %v", mask.URL(o.putURL), err)
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
|
@ -207,7 +206,7 @@ func (o *ObjectstoreStub) completeMultipartUpload(w http.ResponseWriter, r *http
|
|||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
|
@ -76,7 +75,7 @@ func S3ObjectExists(t *testing.T, sess *session.Session, config config.S3Config,
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, int64(len(expectedBytes)), numBytes)
|
||||
|
||||
output, err := ioutil.ReadFile(tmpfile.Name())
|
||||
output, err := os.ReadFile(tmpfile.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, []byte(expectedBytes), output)
|
||||
|
@ -126,7 +125,7 @@ func S3ObjectDoesNotExist(t *testing.T, sess *session.Session, config config.S3C
|
|||
func downloadObject(t *testing.T, sess *session.Session, config config.S3Config, objectName string, handler func(tmpfile *os.File, numBytes int64, err error)) {
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
tmpfile, err := ioutil.TempFile(tmpDir, "s3-output")
|
||||
tmpfile, err := os.CreateTemp(tmpDir, "s3-output")
|
||||
require.NoError(t, err)
|
||||
|
||||
downloadSvc := s3manager.NewDownloader(sess)
|
||||
|
|
|
@ -2,7 +2,7 @@ package destination
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
"testing/iotest"
|
||||
|
@ -19,7 +19,7 @@ func TestHardLimitReader(t *testing.T) {
|
|||
},
|
||||
)
|
||||
|
||||
out, err := ioutil.ReadAll(r)
|
||||
out, err := io.ReadAll(r)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, text, string(out))
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package exif
|
|||
import (
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -75,7 +74,7 @@ func TestNewCleanerWithValidFile(t *testing.T) {
|
|||
cleaner, err := NewCleaner(ctx, input)
|
||||
require.NoError(t, err, "Expected no error when creating cleaner command")
|
||||
|
||||
size, err := io.Copy(ioutil.Discard, cleaner)
|
||||
size, err := io.Copy(io.Discard, cleaner)
|
||||
require.NoError(t, err, "Expected no error when reading output")
|
||||
|
||||
sizeAfterStrip := int64(25399)
|
||||
|
@ -89,7 +88,7 @@ func TestNewCleanerWithInvalidFile(t *testing.T) {
|
|||
cleaner, err := NewCleaner(ctx, strings.NewReader("invalid image"))
|
||||
require.NoError(t, err, "Expected no error when creating cleaner command")
|
||||
|
||||
size, err := io.Copy(ioutil.Discard, cleaner)
|
||||
size, err := io.Copy(io.Discard, cleaner)
|
||||
require.Error(t, err, "Expected error when reading output")
|
||||
require.Equal(t, int64(0), size, "Size of invalid image should be 0")
|
||||
}
|
||||
|
@ -103,7 +102,7 @@ func TestNewCleanerReadingAfterEOF(t *testing.T) {
|
|||
cleaner, err := NewCleaner(ctx, input)
|
||||
require.NoError(t, err, "Expected no error when creating cleaner command")
|
||||
|
||||
_, err = io.Copy(ioutil.Discard, cleaner)
|
||||
_, err = io.Copy(io.Discard, cleaner)
|
||||
require.NoError(t, err, "Expected no error when reading output")
|
||||
|
||||
buf := make([]byte, 1)
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
|
@ -165,7 +164,7 @@ func (rew *rewriter) handleFilePart(r *http.Request, name string, p *multipart.P
|
|||
return err
|
||||
}
|
||||
} else {
|
||||
inputReader = ioutil.NopCloser(p)
|
||||
inputReader = io.NopCloser(p)
|
||||
}
|
||||
|
||||
defer inputReader.Close()
|
||||
|
@ -196,7 +195,7 @@ func (rew *rewriter) handleFilePart(r *http.Request, name string, p *multipart.P
|
|||
}
|
||||
|
||||
func handleExifUpload(ctx context.Context, r io.Reader, filename string, imageType exif.FileType) (io.ReadCloser, error) {
|
||||
tmpfile, err := ioutil.TempFile("", "exifremove")
|
||||
tmpfile, err := os.CreateTemp("", "exifremove")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -265,7 +264,7 @@ func isTIFF(r io.Reader) bool {
|
|||
|
||||
func isJPEG(r io.Reader) bool {
|
||||
// Only the first 512 bytes are used to sniff the content type.
|
||||
buf, err := ioutil.ReadAll(io.LimitReader(r, 512))
|
||||
buf, err := io.ReadAll(io.LimitReader(r, 512))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
|
||||
|
@ -71,7 +71,7 @@ func interceptMultipartFiles(w http.ResponseWriter, r *http.Request, h http.Hand
|
|||
writer.Close()
|
||||
|
||||
// Hijack the request
|
||||
r.Body = ioutil.NopCloser(&body)
|
||||
r.Body = io.NopCloser(&body)
|
||||
r.ContentLength = int64(body.Len())
|
||||
r.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
@ -55,7 +54,7 @@ func TestUploadHandlerForwardingRawData(t *testing.T) {
|
|||
ts := testhelper.TestServerWithHandler(regexp.MustCompile(`/url/path\z`), func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, "PATCH", r.Method, "method")
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "REQUEST", string(body), "request body")
|
||||
|
||||
|
@ -130,7 +129,7 @@ func TestUploadHandlerRewritingMultiPartData(t *testing.T) {
|
|||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
httpRequest = httpRequest.WithContext(ctx)
|
||||
httpRequest.Body = ioutil.NopCloser(&buffer)
|
||||
httpRequest.Body = io.NopCloser(&buffer)
|
||||
httpRequest.ContentLength = int64(buffer.Len())
|
||||
httpRequest.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
response := httptest.NewRecorder()
|
||||
|
@ -419,7 +418,7 @@ func TestContentDispositionRewrite(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestUploadHandlerRemovingExif(t *testing.T) {
|
||||
content, err := ioutil.ReadFile("exif/testdata/sample_exif.jpg")
|
||||
content, err := os.ReadFile("exif/testdata/sample_exif.jpg")
|
||||
require.NoError(t, err)
|
||||
|
||||
runUploadTest(t, content, "sample_exif.jpg", 200, func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -437,7 +436,7 @@ func TestUploadHandlerRemovingExif(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestUploadHandlerRemovingExifTiff(t *testing.T) {
|
||||
content, err := ioutil.ReadFile("exif/testdata/sample_exif.tiff")
|
||||
content, err := os.ReadFile("exif/testdata/sample_exif.tiff")
|
||||
require.NoError(t, err)
|
||||
|
||||
runUploadTest(t, content, "sample_exif.tiff", 200, func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -455,14 +454,14 @@ func TestUploadHandlerRemovingExifTiff(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestUploadHandlerRemovingExifInvalidContentType(t *testing.T) {
|
||||
content, err := ioutil.ReadFile("exif/testdata/sample_exif_invalid.jpg")
|
||||
content, err := os.ReadFile("exif/testdata/sample_exif_invalid.jpg")
|
||||
require.NoError(t, err)
|
||||
|
||||
runUploadTest(t, content, "sample_exif_invalid.jpg", 200, func(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseMultipartForm(100000)
|
||||
require.NoError(t, err)
|
||||
|
||||
output, err := ioutil.ReadFile(r.FormValue("file.path"))
|
||||
output, err := os.ReadFile(r.FormValue("file.path"))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, content, output, "Expected the file to be same as before")
|
||||
|
||||
|
@ -472,7 +471,7 @@ func TestUploadHandlerRemovingExifInvalidContentType(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestUploadHandlerRemovingExifCorruptedFile(t *testing.T) {
|
||||
content, err := ioutil.ReadFile("exif/testdata/sample_exif_corrupted.jpg")
|
||||
content, err := os.ReadFile("exif/testdata/sample_exif_corrupted.jpg")
|
||||
require.NoError(t, err)
|
||||
|
||||
runUploadTest(t, content, "sample_exif_corrupted.jpg", 422, func(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
@ -20,7 +20,7 @@ func TestGzipEncoding(t *testing.T) {
|
|||
fmt.Fprint(w, "test")
|
||||
w.Close()
|
||||
|
||||
body := ioutil.NopCloser(&b)
|
||||
body := io.NopCloser(&b)
|
||||
|
||||
req, err := http.NewRequest("POST", "http://address/test", body)
|
||||
require.NoError(t, err)
|
||||
|
@ -38,7 +38,7 @@ func TestNoEncoding(t *testing.T) {
|
|||
resp := httptest.NewRecorder()
|
||||
|
||||
var b bytes.Buffer
|
||||
body := ioutil.NopCloser(&b)
|
||||
body := io.NopCloser(&b)
|
||||
|
||||
req, err := http.NewRequest("POST", "http://address/test", body)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
|
@ -86,7 +86,7 @@ func testNewBackendRoundTripper(t *testing.T, ts *httptest.Server, tlsClientConf
|
|||
require.NoError(t, err, "perform roundtrip")
|
||||
defer response.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(response.Body)
|
||||
body, err := io.ReadAll(response.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, expectedResponseBody, string(body))
|
||||
|
|
|
@ -3,7 +3,6 @@ package upstream
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
|
@ -287,7 +286,7 @@ func runTestCases(t *testing.T, ws *httptest.Server, testCases []testCase) {
|
|||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, 200, resp.StatusCode, "response code")
|
||||
|
|
|
@ -15,13 +15,13 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
svg "github.com/h2non/go-is-svg"
|
||||
)
|
||||
|
||||
func main() {
|
||||
buf, err := ioutil.ReadFile("_example/example.svg")
|
||||
buf, err := os.ReadFile("_example/example.svg")
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %s\n", err)
|
||||
return
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
|
@ -41,7 +40,7 @@ func validateMetadata(r io.Reader) error {
|
|||
return err
|
||||
}
|
||||
|
||||
meta, err := ioutil.ReadAll(gz)
|
||||
meta, err := io.ReadAll(gz)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -59,7 +58,7 @@ func validateMetadata(r io.Reader) error {
|
|||
func TestGenerateZipMetadataFromFile(t *testing.T) {
|
||||
var metaBuffer bytes.Buffer
|
||||
|
||||
f, err := ioutil.TempFile("", "workhorse-metadata.zip-")
|
||||
f, err := os.CreateTemp("", "workhorse-metadata.zip-")
|
||||
if f != nil {
|
||||
defer os.Remove(f.Name())
|
||||
}
|
||||
|
@ -84,7 +83,7 @@ func TestGenerateZipMetadataFromFile(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestErrNotAZip(t *testing.T) {
|
||||
f, err := ioutil.TempFile("", "workhorse-metadata.zip-")
|
||||
f, err := os.CreateTemp("", "workhorse-metadata.zip-")
|
||||
if f != nil {
|
||||
defer os.Remove(f.Name())
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
goLog "log"
|
||||
"os"
|
||||
|
||||
|
@ -28,7 +27,7 @@ func startLogging(file string, format string) (io.Closer, error) {
|
|||
|
||||
switch format {
|
||||
case noneLogType:
|
||||
return logkit.Initialize(logkit.WithWriter(ioutil.Discard))
|
||||
return logkit.Initialize(logkit.WithWriter(io.Discard))
|
||||
case jsonLogFormat:
|
||||
return logkit.Initialize(
|
||||
logkit.WithOutputName(file),
|
||||
|
@ -53,7 +52,7 @@ func startLogging(file string, format string) (io.Closer, error) {
|
|||
// In text format, we use a separate logger for access logs
|
||||
func getAccessLogger(file string, format string) (*log.Logger, io.Closer, error) {
|
||||
if format != "text" {
|
||||
return log.StandardLogger(), ioutil.NopCloser(nil), nil
|
||||
return log.StandardLogger(), io.NopCloser(nil), nil
|
||||
}
|
||||
|
||||
if file == "" {
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
|
@ -137,7 +136,7 @@ func buildConfig(arg0 string, args []string) (*bootConfig, *config.Config, error
|
|||
|
||||
tomlData := ""
|
||||
if *configFile != "" {
|
||||
buf, err := ioutil.ReadFile(*configFile)
|
||||
buf, err := os.ReadFile(*configFile)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("configFile: %v", err)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"fmt"
|
||||
"image/png"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
|
@ -307,7 +306,7 @@ func TestGzipAssets(t *testing.T) {
|
|||
resp, err := http.DefaultTransport.RoundTrip(req)
|
||||
require.NoError(t, err, desc)
|
||||
defer resp.Body.Close()
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err, desc)
|
||||
|
||||
require.Equal(t, 200, resp.StatusCode, "%s: status code", desc)
|
||||
|
@ -366,7 +365,7 @@ func TestAltDocumentAssets(t *testing.T) {
|
|||
resp, err := http.DefaultTransport.RoundTrip(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
if tc.content != "" {
|
||||
|
@ -412,7 +411,7 @@ func doSendDataRequest(path string, command, literalJSON string) (*http.Response
|
|||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
bodyData, err := ioutil.ReadAll(resp.Body)
|
||||
bodyData, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return resp, nil, err
|
||||
}
|
||||
|
@ -574,7 +573,7 @@ func TestAPIFalsePositivesAreProxied(t *testing.T) {
|
|||
require.NoError(t, err, "%s %q", tc.method, tc.path)
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := ioutil.ReadAll(resp.Body)
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err, "%s %q: reading body", tc.method, tc.path)
|
||||
|
||||
require.Equal(t, 200, resp.StatusCode, "%s %q: status code", tc.method, tc.path)
|
||||
|
@ -833,7 +832,7 @@ func httpGet(t *testing.T, url string, headers map[string]string) (*http.Respons
|
|||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
return resp, string(b)
|
||||
|
|
|
@ -3,7 +3,7 @@ package main
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
@ -51,7 +51,7 @@ func TestProxyRequest(t *testing.T) {
|
|||
"expect Gitlab-Workhorse-Proxy-Start to start with 1",
|
||||
)
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err, "read body")
|
||||
require.Equal(t, "REQUEST", string(body), "body contents")
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -53,14 +53,14 @@ func allowedXSendfileDownload(t *testing.T, contentFilename string, filePath str
|
|||
|
||||
require.NoError(t, os.MkdirAll(cacheDir, 0755))
|
||||
contentBytes := []byte("content")
|
||||
require.NoError(t, ioutil.WriteFile(contentPath, contentBytes, 0644))
|
||||
require.NoError(t, os.WriteFile(contentPath, contentBytes, 0644))
|
||||
|
||||
resp, err := http.Get(fmt.Sprintf("%s/%s", ws.URL, filePath))
|
||||
require.NoError(t, err)
|
||||
|
||||
requireAttachmentName(t, resp, contentFilename)
|
||||
|
||||
actual, err := ioutil.ReadAll(resp.Body)
|
||||
actual, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, resp.Body.Close())
|
||||
|
||||
|
@ -89,7 +89,7 @@ func deniedXSendfileDownload(t *testing.T, contentFilename string, filePath stri
|
|||
|
||||
requireAttachmentName(t, resp, contentFilename)
|
||||
|
||||
actual, err := ioutil.ReadAll(resp.Body)
|
||||
actual, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err, "read body")
|
||||
require.NoError(t, resp.Body.Close())
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
@ -345,7 +344,7 @@ func TestLfsUpload(t *testing.T) {
|
|||
require.Equal(t, oid, r.Form.Get("file.sha256"), "Invalid SHA256 populated")
|
||||
require.Equal(t, strconv.Itoa(len(reqBody)), r.Form.Get("file.size"), "Invalid size populated")
|
||||
|
||||
tempfile, err := ioutil.ReadFile(r.Form.Get("file.path"))
|
||||
tempfile, err := os.ReadFile(r.Form.Get("file.path"))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, reqBody, string(tempfile), "Temporary file has the wrong body")
|
||||
|
||||
|
@ -369,7 +368,7 @@ func TestLfsUpload(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
defer resp.Body.Close()
|
||||
rspData, err := ioutil.ReadAll(resp.Body)
|
||||
rspData, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Expect the (eventual) response to be proxied through, untouched
|
||||
|
@ -431,7 +430,7 @@ func TestLfsUploadRouting(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
rspData, err := ioutil.ReadAll(resp.Body)
|
||||
rspData, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
if tc.match {
|
||||
|
@ -470,7 +469,7 @@ func packageUploadTestServer(t *testing.T, method string, resource string, reqBo
|
|||
require.Equal(t, len, r.Form.Get("file.size"), "Invalid size populated")
|
||||
|
||||
tmpFilePath := r.Form.Get("file.path")
|
||||
fileData, err := ioutil.ReadFile(tmpFilePath)
|
||||
fileData, err := os.ReadFile(tmpFilePath)
|
||||
defer os.Remove(tmpFilePath)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
@ -499,7 +498,7 @@ func testPackageFileUpload(t *testing.T, method string, resource string) {
|
|||
resp, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
|
||||
respData, err := ioutil.ReadAll(resp.Body)
|
||||
respData, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, rspBody, string(respData), "Temporary file has the wrong body")
|
||||
defer resp.Body.Close()
|
||||
|
|
Loading…
Reference in New Issue