Skip to content

Commit 6e71133

Browse files
committed
Add support for --ordered and --version
Increase version to v0.2.1
1 parent d9ae415 commit 6e71133

File tree

5 files changed

+60
-32
lines changed

5 files changed

+60
-32
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# coshell v0.1.5
1+
# coshell v0.2.1
22

33
A no-frills dependency-free replacement for GNU parallel, perfect for initramfs usage.
44

cosh/cosh.go

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* coshell v0.1.5 - a no-frills dependency-free replacement for GNU parallel
3-
* Copyright (C) 2014-2015 gdm85 - https://github.com/gdm85/coshell/
2+
* coshell v0.2.1 - a no-frills dependency-free replacement for GNU parallel
3+
* Copyright (C) 2014-2018 gdm85 - https://github.com/gdm85/coshell/
44
55
This program is free software; you can redistribute it and/or
66
modify it under the terms of the GNU General Public License
@@ -106,10 +106,14 @@ type CommandGroup struct {
106106
deinterlace bool
107107
halt bool
108108
masterId int
109+
ordered bool
109110
}
110111

111-
func NewCommandGroup(deinterlace, halt bool, masterId int) *CommandGroup {
112-
return &CommandGroup{deinterlace: deinterlace, halt: halt, masterId: masterId}
112+
func NewCommandGroup(deinterlace, halt bool, masterId int, ordered bool) *CommandGroup {
113+
if ordered {
114+
deinterlace = true
115+
}
116+
return &CommandGroup{deinterlace: deinterlace, halt: halt, masterId: masterId, ordered: ordered}
113117
}
114118

115119
func (cg *CommandGroup) Start() error {
@@ -125,44 +129,60 @@ func (cg *CommandGroup) Start() error {
125129
}
126130

127131
type event struct {
128-
i int
132+
index int
129133
error error
130134
exitCode int
131135
}
132136

133137
// Returns sum of all exit codes of individual commands
134138
func (cg *CommandGroup) Join() (err error, exitCode int) {
135139

136-
chainOfEvents := make(chan event, len(cg.commands))
140+
completedCommands := make(chan event, len(cg.commands))
137141

138142
// join all and update cumulative exit status
139143
for i := 0; i < len(cg.commands); i++ {
140144
go func(i int) {
141145
if err := cg.commands[i].Wait(); err != nil {
142146
if exitError, ok := err.(*exec.ExitError); ok {
143147
if status, ok := exitError.Sys().(syscall.WaitStatus); ok {
144-
chainOfEvents <- event{i: i, exitCode: status.ExitStatus()}
148+
completedCommands <- event{index: i, exitCode: status.ExitStatus()}
145149
return
146150
} else {
147-
chainOfEvents <- event{i: i, error: errors.New("cannot read exit error status")}
151+
completedCommands <- event{index: i, error: errors.New("cannot read exit error status")}
148152
return
149153
}
150154
} else {
151-
chainOfEvents <- event{i: i, error: err}
155+
completedCommands <- event{index: i, error: err}
152156
return
153157
}
154158
}
155159

156-
chainOfEvents <- event{i: i, exitCode: 0}
160+
// completed successfully
161+
completedCommands <- event{index: i, exitCode: 0}
157162
}(i)
158163
}
159164

165+
orderedDisplay := make([]event, len(cg.commands))
166+
displayedSoFar := 0
167+
160168
count := 0
161-
for ev := range chainOfEvents {
169+
for ev := range completedCommands {
162170
// print deinterlaced output
163171
if cg.deinterlace {
164-
if err = cg.outputs[ev.i].ReplayOutputs(); err != nil {
165-
return
172+
if cg.ordered {
173+
// store ordered
174+
orderedDisplay[ev.index] = ev
175+
176+
if displayedSoFar == ev.index {
177+
if err = cg.outputs[ev.index].ReplayOutputs(); err != nil {
178+
return
179+
}
180+
displayedSoFar++
181+
}
182+
} else {
183+
if err = cg.outputs[ev.index].ReplayOutputs(); err != nil {
184+
return
185+
}
166186
}
167187
}
168188

@@ -180,9 +200,9 @@ func (cg *CommandGroup) Join() (err error, exitCode int) {
180200
}
181201

182202
// make these objects no more usable
183-
cg.commands[ev.i] = nil
203+
cg.commands[ev.index] = nil
184204
if cg.deinterlace {
185-
cg.outputs[ev.i] = nil
205+
cg.outputs[ev.index] = nil
186206
}
187207

188208
if cg.halt && ev.exitCode != 0 {
@@ -200,7 +220,8 @@ func (cg *CommandGroup) Join() (err error, exitCode int) {
200220
return
201221
}
202222

203-
if cg.masterId != -1 && cg.masterId == ev.i {
223+
// if master aborts, show its output
224+
if cg.masterId != -1 && cg.masterId == ev.index {
204225
if cg.deinterlace {
205226
// dump outputs that are available
206227
for _, output := range cg.outputs {
@@ -221,11 +242,11 @@ func (cg *CommandGroup) Join() (err error, exitCode int) {
221242

222243
func (cg *CommandGroup) Add(commandLines ...string) error {
223244
// some common values for all commands
224-
env := os.Environ()
225245
cwd, err := os.Getwd()
226246
if err != nil {
227247
return err
228248
}
249+
env := os.Environ()
229250

230251
// prepare commands to be executed
231252
commands := make([]*exec.Cmd, len(commandLines))

cosh/cosh_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* coshell v0.1.5 - a no-frills dependency-free replacement for GNU parallel
3-
* Copyright (C) 2014-2015 gdm85 - https://github.com/gdm85/coshell/
2+
* coshell v0.2.1 - a no-frills dependency-free replacement for GNU parallel
3+
* Copyright (C) 2014-2018 gdm85 - https://github.com/gdm85/coshell/
44
55
This program is free software; you can redistribute it and/or
66
modify it under the terms of the GNU General Public License
@@ -25,24 +25,24 @@ import (
2525

2626
type OptionsCombination struct {
2727
Deinterlace bool
28-
Halt bool
28+
Halt bool
2929
}
3030

3131
var (
3232
combinations = []OptionsCombination{
33-
{true,true},
34-
{false,true},
35-
{true,false},
36-
{false,false},
33+
{true, true},
34+
{false, true},
35+
{true, false},
36+
{false, false},
3737
}
3838
testCommandLines = []string{"echo alpha >/dev/null", "echo beta >/dev/null", "echo gamma >/dev/null", "echo delta >/dev/null"}
3939
)
4040

4141
func TestCommandGroupOptions(t *testing.T) {
4242
for _, c := range combinations {
43-
for masterId := -1; masterId<len(testCommandLines); masterId++ {
43+
for masterId := -1; masterId < len(testCommandLines); masterId++ {
4444
var exitCode int
45-
cg := NewCommandGroup(c.Deinterlace, c.Halt, masterId)
45+
cg := NewCommandGroup(c.Deinterlace, c.Halt, masterId, false)
4646
err := cg.Add(testCommandLines...)
4747
if err != nil {
4848
t.Fatal(err.Error())

coshell.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* coshell v0.1.5 - a no-frills dependency-free replacement for GNU parallel
3-
* Copyright (C) 2014-2015 gdm85 - https://github.com/gdm85/coshell/
2+
* coshell v0.2.1 - a no-frills dependency-free replacement for GNU parallel
3+
* Copyright (C) 2014-2018 gdm85 - https://github.com/gdm85/coshell/
44
55
This program is free software; you can redistribute it and/or
66
modify it under the terms of the GNU General Public License
@@ -37,7 +37,7 @@ func fatal(err error) {
3737
}
3838

3939
func main() {
40-
var deinterlace, halt, nextMightBeMasterId bool
40+
var deinterlace, ordered, halt, nextMightBeMasterId bool
4141
masterId := -1
4242
if len(os.Args) > 1 {
4343
for i := 1; i < len(os.Args); i++ {
@@ -97,19 +97,26 @@ func main() {
9797

9898
switch os.Args[i] {
9999
case "--help", "-h":
100-
fmt.Printf("coshell v0.1.4 by gdm85 - Licensed under GNU GPLv2\n")
100+
fmt.Printf("coshell v0.2.1 by gdm85 - Licensed under GNU GPLv2\n")
101101
fmt.Printf("Usage:\n\tcoshell [--help|-h] [--deinterlace|-d] [--halt-all|-a] < list-of-commands\n")
102102
fmt.Printf("\t\t--deinterlace | -d\t\tShow individual output of processes in blocks, second order of termination\n\n")
103+
fmt.Printf("\t\t--ordered | -o\t\tImplies --deinterlace, will output block of processes one after another, second original order specified in input\n\n")
103104
fmt.Printf("\t\t--halt-all | -a\t\tTerminate neighbour processes as soon as any has failed, using its exit code\n\n")
104105
fmt.Printf("\t\t--master=0 | -m=0\t\tTerminate neighbour processes as soon as command from specified input line exits and use its exit code; if no id is specified, 0 is assumed\n\n")
105106
fmt.Printf("Each line read from standard input will be run as a command via `sh -c`\n")
106107
os.Exit(0)
108+
case "--version", "-v":
109+
fmt.Printf("coshell v0.2.1 by gdm85 - Licensed under GNU GPLv2\n")
110+
os.Exit(0)
107111
case "--halt-all", "-a":
108112
halt = true
109113
continue
110114
case "--deinterlace", "-d":
111115
deinterlace = true
112116
continue
117+
case "--ordered", "-o":
118+
ordered = true
119+
continue
113120
default:
114121
fmt.Fprintf(os.Stderr, "Invalid parameter specified: %s\n", os.Args[i])
115122
}
@@ -146,7 +153,7 @@ func main() {
146153
return
147154
}
148155

149-
cg := cosh.NewCommandGroup(deinterlace, halt, masterId)
156+
cg := cosh.NewCommandGroup(deinterlace, halt, masterId, ordered)
150157

151158
err := cg.Add(commandLines...)
152159
if err != nil {
File renamed without changes.

0 commit comments

Comments
 (0)