Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
CMake
CMake
Commits
64f987c1
Commit
64f987c1
authored
Jan 08, 2017
by
Daniel Pfeifer
Committed by
wahikihiki
Aug 06, 2019
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cmFileCommand: port to cmExecutionStatus
parent
53fc083d
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
408 additions
and
359 deletions
+408
-359
Source/cmFileCommand.cxx
Source/cmFileCommand.cxx
+306
-283
Source/cmFileCommand.h
Source/cmFileCommand.h
+54
-28
Source/cmFileCopier.cxx
Source/cmFileCopier.cxx
+23
-23
Source/cmFileCopier.h
Source/cmFileCopier.h
+3
-3
Source/cmFileInstaller.cxx
Source/cmFileInstaller.cxx
+20
-20
Source/cmFileInstaller.h
Source/cmFileInstaller.h
+2
-2
No files found.
Source/cmFileCommand.cxx
View file @
64f987c1
This diff is collapsed.
Click to expand it.
Source/cmFileCommand.h
View file @
64f987c1
...
...
@@ -37,43 +37,69 @@ public:
cmExecutionStatus
&
status
)
override
;
protected:
bool
HandleRename
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleRemove
(
std
::
vector
<
std
::
string
>
const
&
args
,
bool
recurse
);
bool
HandleWriteCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
bool
append
);
bool
HandleReadCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleHashCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleStringsCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleGlobCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
bool
recurse
);
bool
HandleTouchCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
bool
create
);
bool
HandleMakeDirectoryCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleRename
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleRemove
(
std
::
vector
<
std
::
string
>
const
&
args
,
bool
recurse
,
cmExecutionStatus
&
status
);
bool
HandleWriteCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
bool
append
,
cmExecutionStatus
&
status
);
bool
HandleReadCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleHashCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleStringsCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleGlobCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
bool
recurse
,
cmExecutionStatus
&
status
);
bool
HandleTouchCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
bool
create
,
cmExecutionStatus
&
status
);
bool
HandleMakeDirectoryCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleRelativePathCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleRelativePathCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleCMakePathCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
bool
nativePath
);
bool
HandleReadElfCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleRPathChangeCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleRPathCheckCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleRPathRemoveCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleDifferentCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
nativePath
,
cmExecutionStatus
&
status
);
bool
HandleReadElfCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleRPathChangeCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleRPathCheckCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleRPathRemoveCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleDifferentCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleCopyCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleInstallCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleDownloadCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleUploadCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleCopyCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleInstallCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleDownloadCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleUploadCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleTimestampCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleGenerateCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleLockCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleSizeCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleReadSymlinkCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleCreateLinkCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
bool
HandleTimestampCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleGenerateCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleLockCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleSizeCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleReadSymlinkCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleCreateLinkCommand
(
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
bool
HandleGetRuntimeDependenciesCommand
(
std
::
vector
<
std
::
string
>
const
&
args
);
std
::
vector
<
std
::
string
>
const
&
args
,
cmExecutionStatus
&
status
);
private:
void
AddEvaluationFile
(
const
std
::
string
&
inputName
,
const
std
::
string
&
outputExpr
,
const
std
::
string
&
condition
,
bool
inputIsContent
);
const
std
::
string
&
condition
,
bool
inputIsContent
,
cmExecutionStatus
&
status
);
};
#endif
Source/cmFileCopier.cxx
View file @
64f987c1
...
...
@@ -3,8 +3,8 @@
#include "cmFileCopier.h"
#include "cmExecutionStatus.h"
#include "cmFSPermissions.h"
#include "cmFileCommand.h"
#include "cmFileTimes.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
...
...
@@ -20,9 +20,9 @@
using
namespace
cmFSPermissions
;
cmFileCopier
::
cmFileCopier
(
cm
FileCommand
*
command
,
const
char
*
name
)
:
FileCommand
(
command
)
,
Makefile
(
command
->
GetMakefile
())
cmFileCopier
::
cmFileCopier
(
cm
ExecutionStatus
&
status
,
const
char
*
name
)
:
Status
(
status
)
,
Makefile
(
&
status
.
GetMakefile
())
,
Name
(
name
)
,
Always
(
false
)
,
MatchlessFiles
(
true
)
...
...
@@ -91,7 +91,7 @@ bool cmFileCopier::SetPermissions(const std::string& toFile,
if
(
!
cmSystemTools
::
SetPermissions
(
toFile
,
permissions
))
{
std
::
ostringstream
e
;
e
<<
this
->
Name
<<
" cannot set permissions on
\"
"
<<
toFile
<<
"
\"
"
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
}
...
...
@@ -105,7 +105,7 @@ bool cmFileCopier::CheckPermissions(std::string const& arg,
if
(
!
cmFSPermissions
::
stringToModeT
(
arg
,
permissions
))
{
std
::
ostringstream
e
;
e
<<
this
->
Name
<<
" given invalid permission
\"
"
<<
arg
<<
"
\"
."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
return
true
;
...
...
@@ -121,7 +121,7 @@ bool cmFileCopier::ReportMissing(const std::string& fromFile)
// The input file does not exist and installation is not optional.
std
::
ostringstream
e
;
e
<<
this
->
Name
<<
" cannot find
\"
"
<<
fromFile
<<
"
\"
."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
...
...
@@ -129,7 +129,7 @@ void cmFileCopier::NotBeforeMatch(std::string const& arg)
{
std
::
ostringstream
e
;
e
<<
"option "
<<
arg
<<
" may not appear before PATTERN or REGEX."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
this
->
Doing
=
DoingError
;
}
...
...
@@ -137,7 +137,7 @@ void cmFileCopier::NotAfterMatch(std::string const& arg)
{
std
::
ostringstream
e
;
e
<<
"option "
<<
arg
<<
" may not appear after PATTERN or REGEX."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
this
->
Doing
=
DoingError
;
}
...
...
@@ -174,7 +174,7 @@ bool cmFileCopier::GetDefaultDirectoryPermissions(mode_t** mode)
cmSystemTools
::
ExpandListArgument
(
default_dir_install_permissions
,
items
);
for
(
const
auto
&
arg
:
items
)
{
if
(
!
this
->
CheckPermissions
(
arg
,
**
mode
))
{
this
->
FileCommand
->
SetError
(
this
->
Status
.
SetError
(
" Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable."
);
return
false
;
}
...
...
@@ -194,7 +194,7 @@ bool cmFileCopier::Parse(std::vector<std::string> const& args)
if
(
!
this
->
CheckKeyword
(
args
[
i
])
&&
!
this
->
CheckValue
(
args
[
i
]))
{
std
::
ostringstream
e
;
e
<<
"called with unknown argument
\"
"
<<
args
[
i
]
<<
"
\"
."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
...
...
@@ -208,7 +208,7 @@ bool cmFileCopier::Parse(std::vector<std::string> const& args)
if
(
this
->
Destination
.
empty
())
{
std
::
ostringstream
e
;
e
<<
this
->
Name
<<
" given no DESTINATION"
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
...
...
@@ -341,7 +341,7 @@ bool cmFileCopier::CheckValue(std::string const& arg)
}
else
{
std
::
ostringstream
e
;
e
<<
"could not compile PATTERN
\"
"
<<
arg
<<
"
\"
."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
this
->
Doing
=
DoingError
;
}
}
break
;
...
...
@@ -353,7 +353,7 @@ bool cmFileCopier::CheckValue(std::string const& arg)
}
else
{
std
::
ostringstream
e
;
e
<<
"could not compile REGEX
\"
"
<<
arg
<<
"
\"
."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
this
->
Doing
=
DoingError
;
}
break
;
...
...
@@ -396,8 +396,8 @@ bool cmFileCopier::Run(std::vector<std::string> const& args)
file
+=
"/"
;
file
+=
f
;
}
else
if
(
!
this
->
FilesFromDir
.
empty
())
{
this
->
FileCommand
->
SetError
(
"option FILES_FROM_DIR requires all files "
"to be specified as relative paths."
);
this
->
Status
.
SetError
(
"option FILES_FROM_DIR requires all files "
"to be specified as relative paths."
);
return
false
;
}
else
{
file
=
f
;
...
...
@@ -446,7 +446,7 @@ bool cmFileCopier::Install(const std::string& fromFile,
if
(
fromFile
.
empty
())
{
std
::
ostringstream
e
;
e
<<
"INSTALL encountered an empty string input file name."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
...
...
@@ -514,7 +514,7 @@ bool cmFileCopier::InstallSymlinkChain(std::string& fromFile,
if
(
!
cmSystemTools
::
CreateSymlink
(
symlinkTarget
,
toFile
))
{
std
::
ostringstream
e
;
e
<<
this
->
Name
<<
" cannot create symlink
\"
"
<<
toFile
<<
"
\"
."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
}
...
...
@@ -535,7 +535,7 @@ bool cmFileCopier::InstallSymlink(const std::string& fromFile,
std
::
ostringstream
e
;
e
<<
this
->
Name
<<
" cannot read symlink
\"
"
<<
fromFile
<<
"
\"
to duplicate at
\"
"
<<
toFile
<<
"
\"
."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
...
...
@@ -566,7 +566,7 @@ bool cmFileCopier::InstallSymlink(const std::string& fromFile,
std
::
ostringstream
e
;
e
<<
this
->
Name
<<
" cannot duplicate symlink
\"
"
<<
fromFile
<<
"
\"
at
\"
"
<<
toFile
<<
"
\"
."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
}
...
...
@@ -595,7 +595,7 @@ bool cmFileCopier::InstallFile(const std::string& fromFile,
std
::
ostringstream
e
;
e
<<
this
->
Name
<<
" cannot copy file
\"
"
<<
fromFile
<<
"
\"
to
\"
"
<<
toFile
<<
"
\"
."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
...
...
@@ -611,7 +611,7 @@ bool cmFileCopier::InstallFile(const std::string& fromFile,
std
::
ostringstream
e
;
e
<<
this
->
Name
<<
" cannot set modification time on
\"
"
<<
toFile
<<
"
\"
"
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
}
...
...
@@ -648,7 +648,7 @@ bool cmFileCopier::InstallDirectory(const std::string& source,
std
::
ostringstream
e
;
e
<<
this
->
Name
<<
" cannot make directory
\"
"
<<
destination
<<
"
\"
: "
<<
cmSystemTools
::
GetLastSystemError
();
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
...
...
Source/cmFileCopier.h
View file @
64f987c1
...
...
@@ -12,19 +12,19 @@
#include <string>
#include <vector>
class
cm
FileCommand
;
class
cm
ExecutionStatus
;
class
cmMakefile
;
// File installation helper class.
struct
cmFileCopier
{
cmFileCopier
(
cm
FileCommand
*
command
,
const
char
*
name
=
"COPY"
);
cmFileCopier
(
cm
ExecutionStatus
&
status
,
const
char
*
name
=
"COPY"
);
virtual
~
cmFileCopier
();
bool
Run
(
std
::
vector
<
std
::
string
>
const
&
args
);
protected:
cm
FileCommand
*
FileCommand
;
cm
ExecutionStatus
&
Status
;
cmMakefile
*
Makefile
;
const
char
*
Name
;
bool
Always
;
...
...
Source/cmFileInstaller.cxx
View file @
64f987c1
...
...
@@ -3,8 +3,8 @@
#include "cmFileInstaller.h"
#include "cmExecutionStatus.h"
#include "cmFSPermissions.h"
#include "cmFileCommand.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
...
...
@@ -14,8 +14,8 @@
using
namespace
cmFSPermissions
;
cmFileInstaller
::
cmFileInstaller
(
cm
FileCommand
*
command
)
:
cmFileCopier
(
command
,
"INSTALL"
)
cmFileInstaller
::
cmFileInstaller
(
cm
ExecutionStatus
&
status
)
:
cmFileCopier
(
status
,
"INSTALL"
)
,
InstallType
(
cmInstallType_FILES
)
,
Optional
(
false
)
,
MessageAlways
(
false
)
...
...
@@ -111,19 +111,19 @@ bool cmFileInstaller::Parse(std::vector<std::string> const& args)
if
(
!
this
->
Rename
.
empty
())
{
if
(
!
this
->
FilesFromDir
.
empty
())
{
this
->
FileCommand
->
SetError
(
"INSTALL option RENAME may not be "
"combined with FILES_FROM_DIR."
);
this
->
Status
.
SetError
(
"INSTALL option RENAME may not be "
"combined with FILES_FROM_DIR."
);
return
false
;
}
if
(
this
->
InstallType
!=
cmInstallType_FILES
&&
this
->
InstallType
!=
cmInstallType_PROGRAMS
)
{
this
->
FileCommand
->
SetError
(
"INSTALL option RENAME may be used "
"only with FILES or PROGRAMS."
);
this
->
Status
.
SetError
(
"INSTALL option RENAME may be used "
"only with FILES or PROGRAMS."
);
return
false
;
}
if
(
this
->
Files
.
size
()
>
1
)
{
this
->
FileCommand
->
SetError
(
"INSTALL option RENAME may be used "
"only with one file."
);
this
->
Status
.
SetError
(
"INSTALL option RENAME may be used "
"only with one file."
);
return
false
;
}
}
...
...
@@ -134,9 +134,9 @@ bool cmFileInstaller::Parse(std::vector<std::string> const& args)
if
(((
this
->
MessageAlways
?
1
:
0
)
+
(
this
->
MessageLazy
?
1
:
0
)
+
(
this
->
MessageNever
?
1
:
0
))
>
1
)
{
this
->
FileCommand
->
SetError
(
"INSTALL options MESSAGE_ALWAYS, "
"MESSAGE_LAZY, and MESSAGE_NEVER "
"are mutually exclusive."
);
this
->
Status
.
SetError
(
"INSTALL options MESSAGE_ALWAYS, "
"MESSAGE_LAZY, and MESSAGE_NEVER "
"are mutually exclusive."
);
return
false
;
}
...
...
@@ -213,7 +213,7 @@ bool cmFileInstaller::CheckKeyword(std::string const& arg)
e
<<
"INSTALL called with old-style "
<<
arg
<<
" argument. "
<<
"This script was generated with an older version of CMake. "
<<
"Re-run this cmake version on your build tree."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
this
->
Doing
=
DoingError
;
}
else
{
return
this
->
cmFileCopier
::
CheckKeyword
(
arg
);
...
...
@@ -257,7 +257,7 @@ bool cmFileInstaller::GetTargetTypeFromString(const std::string& stype)
}
else
{
std
::
ostringstream
e
;
e
<<
"Option TYPE given unknown value
\"
"
<<
stype
<<
"
\"
."
;
this
->
FileCommand
->
SetError
(
e
.
str
());
this
->
Status
.
SetError
(
e
.
str
());
return
false
;
}
return
true
;
...
...
@@ -269,8 +269,8 @@ bool cmFileInstaller::HandleInstallDestination()
// allow for / to be a valid destination
if
(
destination
.
size
()
<
2
&&
destination
!=
"/"
)
{
this
->
FileCommand
->
SetError
(
"called with inappropriate arguments. "
"No DESTINATION provided or ."
);
this
->
Status
.
SetError
(
"called with inappropriate arguments. "
"No DESTINATION provided or ."
);
return
false
;
}
...
...
@@ -300,7 +300,7 @@ bool cmFileInstaller::HandleInstallDestination()
if
(
relative
)
{
// This is relative path on unix or windows. Since we are doing
// destdir, this case does not make sense.
this
->
FileCommand
->
SetError
(
this
->
Status
.
SetError
(
"called with relative DESTINATION. This "
"does not make sense when using DESTDIR. Specify "
"absolute path or remove DESTDIR environment variable."
);
...
...
@@ -315,7 +315,7 @@ bool cmFileInstaller::HandleInstallDestination()
"absolute path or remove DESTDIR environment variable."
"
\n
DESTINATION=
\n
"
;
message
+=
destination
;
this
->
FileCommand
->
SetError
(
message
);
this
->
Status
.
SetError
(
message
);
return
false
;
}
}
...
...
@@ -335,14 +335,14 @@ bool cmFileInstaller::HandleInstallDestination()
if
(
!
cmSystemTools
::
MakeDirectory
(
destination
,
default_dir_mode
))
{
std
::
string
errstring
=
"cannot create directory: "
+
destination
+
". Maybe need administrative privileges."
;
this
->
FileCommand
->
SetError
(
errstring
);
this
->
Status
.
SetError
(
errstring
);
return
false
;
}
}
if
(
!
cmSystemTools
::
FileIsDirectory
(
destination
))
{
std
::
string
errstring
=
"INSTALL destination: "
+
destination
+
" is not a directory."
;
this
->
FileCommand
->
SetError
(
errstring
);
this
->
Status
.
SetError
(
errstring
);
return
false
;
}
}
...
...
Source/cmFileInstaller.h
View file @
64f987c1
...
...
@@ -12,11 +12,11 @@
#include <string>
#include <vector>
class
cm
FileCommand
;
class
cm
ExecutionStatus
;
struct
cmFileInstaller
:
public
cmFileCopier
{
cmFileInstaller
(
cm
FileCommand
*
command
);
cmFileInstaller
(
cm
ExecutionStatus
&
status
);
~
cmFileInstaller
()
override
;
protected:
...
...
Brad King
@brad.king
mentioned in commit
1996e015
·
Aug 09, 2019
mentioned in commit
1996e015
mentioned in commit 1996e0157826903f27f73825a01f83d53dc8fba4
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment