grim/hgkeeper
Clone
Summary
Browse
Changes
Graph
Add support for specifying which mercurial executable to use
14 months ago, Gary Kramlich
8275959b76f0
Add support for specifying which mercurial executable to use
package
hg
import
(
"errors"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
log
"github.com/sirupsen/logrus"
"keep.imfreedom.org/grim/hgkeeper/access"
)
var
(
hgExe
string
)
type
Command
struct
{
cmd
*
exec
.
Cmd
tmpHgrc
string
writeable
bool
}
func
SetExe
(
path
string
)
error
{
path
,
err
:=
exec
.
LookPath
(
path
)
if
err
!=
nil
{
if
!
errors
.
Is
(
err
,
exec
.
ErrDot
)
{
return
err
}
}
hgExe
=
path
return
nil
}
func
(
c
*
Command
)
Setup
(
repoName
,
username
string
)
error
{
hgrc
,
err
:=
createHgrc
(
c
.
writeable
)
if
err
!=
nil
{
return
err
}
c
.
tmpHgrc
=
hgrc
// site.hgrc is deprecated, but we still support it for now
rcs
:=
[]
string
{
filepath
.
Join
(
access
.
AdminRepoPath
(),
"site.hgrc"
)}
// add the repo specific hgrc's
rcs
=
append
(
rcs
,
findHgrcsForRepo
(
repoName
)
...
)
// add the hgrc that controls writability
rcs
=
append
(
rcs
,
c
.
tmpHgrc
)
c
.
cmd
.
Env
=
append
(
os
.
Environ
(),
"HGRCPATH="
+
strings
.
Join
(
rcs
,
string
(
filepath
.
ListSeparator
)),
"HGK_REPOSITORY="
+
repoName
,
"HGK_USERNAME="
+
username
,
)
return
nil
}
func
(
c
*
Command
)
Teardown
()
{
if
c
.
tmpHgrc
!=
""
{
if
err
:=
os
.
Remove
(
c
.
tmpHgrc
);
err
!=
nil
{
log
.
Warnf
(
"failed to remove %q: %v"
,
c
.
tmpHgrc
,
err
)
}
c
.
tmpHgrc
=
""
}
}
func
(
c
*
Command
)
Exec
(
repoName
,
username
string
)
(
string
,
error
)
{
c
.
Setup
(
repoName
,
username
)
defer
c
.
Teardown
()
raw
,
err
:=
c
.
Cmd
().
CombinedOutput
()
return
string
(
raw
),
err
}
func
(
c
*
Command
)
ExecPiped
(
repoName
,
username
string
,
stdin
io
.
Reader
,
stdout
,
stderr
io
.
Writer
)
error
{
if
err
:=
c
.
Setup
(
repoName
,
username
);
err
!=
nil
{
return
err
}
defer
c
.
Teardown
()
cmd
:=
c
.
Cmd
()
pstdout
,
err
:=
cmd
.
StdoutPipe
()
if
err
!=
nil
{
return
err
}
pstderr
,
err
:=
cmd
.
StderrPipe
()
if
err
!=
nil
{
return
err
}
pstdin
,
err
:=
cmd
.
StdinPipe
()
if
err
!=
nil
{
return
err
}
wg
:=
&
sync
.
WaitGroup
{}
// we wait for stderr and stdout to finish
wg
.
Add
(
2
)
if
err
:=
cmd
.
Start
();
err
!=
nil
{
return
err
}
go
func
()
{
defer
pstdin
.
Close
()
if
_
,
err
:=
io
.
Copy
(
pstdin
,
stdin
);
err
!=
nil
{
log
.
Errorf
(
"Failed to read stdin: %v"
,
err
)
}
}()
go
func
()
{
defer
wg
.
Done
()
if
_
,
err
:=
io
.
Copy
(
stdout
,
pstdout
);
err
!=
nil
{
log
.
Errorf
(
"Failed to write stdout: %v"
,
err
)
}
}()
go
func
()
{
defer
wg
.
Done
()
if
_
,
err
:=
io
.
Copy
(
stderr
,
pstderr
);
err
!=
nil
{
log
.
Errorf
(
"Failed to write stderr: %v"
,
err
)
}
}()
// wait until all output is processed
wg
.
Wait
()
return
cmd
.
Wait
()
}
func
(
c
*
Command
)
Cmd
()
*
exec
.
Cmd
{
return
c
.
cmd
}
func
Init
(
path
string
)
*
Command
{
return
&
Command
{
cmd
:
exec
.
Command
(
hgExe
,
"init"
,
path
),
}
}
func
Serve
(
path
string
,
writeable
bool
)
*
Command
{
return
&
Command
{
cmd
:
exec
.
Command
(
hgExe
,
"-R"
,
path
,
"serve"
,
"--stdio"
),
writeable
:
writeable
,
}
}
func
Add
(
path
string
,
files
...
string
)
*
Command
{
args
:=
append
([]
string
{
"add"
,
"--cwd"
,
path
},
files
...
)
return
&
Command
{
cmd
:
exec
.
Command
(
hgExe
,
args
...
),
}
}
func
Commit
(
path
,
username
,
message
string
)
*
Command
{
args
:=
[]
string
{
"commit"
,
"--cwd"
,
path
,
"--config"
,
"ui.username="
+
username
,
"-m"
,
message
,
}
return
&
Command
{
cmd
:
exec
.
Command
(
hgExe
,
args
...
),
}
}
func
Config
(
setting
string
)
*
Command
{
args
:=
[]
string
{
"config"
,
setting
,
}
return
&
Command
{
cmd
:
exec
.
Command
(
hgExe
,
args
...
),
}
}