rl-workspaces 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +234 -193
  2. package/bin/rl +2 -54
  3. package/dist/agent-launch.js +1 -1
  4. package/dist/agent-presets.js +42 -17
  5. package/dist/agent-resume.js +2 -2
  6. package/dist/agent-runner.js +20 -0
  7. package/dist/agent-workflows.js +60 -16
  8. package/dist/automation-config.js +144 -5
  9. package/dist/bootstrap.js +74 -0
  10. package/dist/cli.js +2 -0
  11. package/dist/command-context.js +1 -1
  12. package/dist/common.js +3 -2
  13. package/dist/dependencies.js +197 -0
  14. package/dist/doctor.js +1 -1
  15. package/dist/git-workflow.js +8 -102
  16. package/dist/help.js +113 -116
  17. package/dist/hooks.js +1 -1
  18. package/dist/install.js +143 -0
  19. package/dist/mcp-setup.js +171 -0
  20. package/dist/mcp.js +13 -16
  21. package/dist/picker.js +24 -7
  22. package/dist/pr-workflow.js +7 -28
  23. package/dist/repos.js +5 -1
  24. package/dist/session-workflows.js +122 -18
  25. package/dist/session.js +1 -1
  26. package/dist/state.js +4 -14
  27. package/dist/storage.js +2 -2
  28. package/dist/store.js +2 -2
  29. package/dist/summary.js +1 -1
  30. package/dist/workflow-collaboration.js +531 -0
  31. package/dist/workflow.js +24 -38
  32. package/lib/entry.zsh +54 -0
  33. package/lib/rl.zsh +37 -9
  34. package/node_modules/proper-lockfile/CHANGELOG.md +108 -0
  35. package/node_modules/smol-toml/LICENSE +24 -0
  36. package/node_modules/smol-toml/README.md +605 -0
  37. package/node_modules/smol-toml/dist/date.d.ts +41 -0
  38. package/node_modules/smol-toml/dist/date.js +156 -0
  39. package/node_modules/smol-toml/dist/error.d.ts +37 -0
  40. package/node_modules/smol-toml/dist/error.js +67 -0
  41. package/node_modules/smol-toml/dist/extract.js +293 -0
  42. package/node_modules/smol-toml/dist/index.cjs +771 -0
  43. package/node_modules/smol-toml/dist/index.d.ts +44 -0
  44. package/node_modules/smol-toml/dist/index.js +34 -0
  45. package/node_modules/smol-toml/dist/parse.d.ts +73 -0
  46. package/node_modules/smol-toml/dist/parse.js +164 -0
  47. package/node_modules/smol-toml/dist/primitive.js +151 -0
  48. package/node_modules/smol-toml/dist/stringify.d.ts +32 -0
  49. package/node_modules/smol-toml/dist/stringify.js +219 -0
  50. package/node_modules/smol-toml/dist/struct.js +156 -0
  51. package/node_modules/smol-toml/dist/util.d.ts +43 -0
  52. package/node_modules/smol-toml/dist/util.js +57 -0
  53. package/node_modules/smol-toml/package.json +68 -0
  54. package/package.json +6 -3
  55. package/shell/rl.zsh +1 -1
package/dist/workflow.js CHANGED
@@ -16,8 +16,6 @@ const COMMAND_OPTIONS = {
16
16
  exec: ["workspace"],
17
17
  setup: ["workspace", "dry-run"],
18
18
  switch: ["create", "base", "no-fetch", "setup", "agent", "output-path"],
19
- new: ["base", "no-fetch", "setup", "output-path"],
20
- open: ["branch", "base", "no-fetch", "setup", "output-path"],
21
19
  };
22
20
  async function createWorkspace(context, name, base, noFetch, options = {}) {
23
21
  if (name.startsWith("-") ||
@@ -29,8 +27,7 @@ async function createWorkspace(context, name, base, noFetch, options = {}) {
29
27
  throw new Error(`Invalid workspace name: ${name}`);
30
28
  git(context.repo, "check-ref-format", "--branch", name);
31
29
  return locked(path.join(context.store.root, CREATE_LOCK), LOCK_FILE, async () => {
32
- const directoryName = options.directoryName ?? name;
33
- const destination = path.resolve(context.managedDir, directoryName);
30
+ const destination = path.resolve(context.managedDir, name);
34
31
  if (!inside(destination, context.managedDir) ||
35
32
  canonical(destination) !== destination)
36
33
  throw new Error("Workspace path must stay inside the managed directory without symlinks");
@@ -41,7 +38,7 @@ async function createWorkspace(context, name, base, noFetch, options = {}) {
41
38
  const [root, branch] = context.store.worktree(registered.worktree);
42
39
  if (branch !== name)
43
40
  throw new Error("Workspace branch changed during selection; retry");
44
- return { path: root, name: directoryName, branch, created: false };
41
+ return { path: root, name, branch, created: false };
45
42
  }
46
43
  if (fs.existsSync(destination))
47
44
  throw new Error(`Workspace path already exists: ${destination}`);
@@ -83,7 +80,7 @@ async function createWorkspace(context, name, base, noFetch, options = {}) {
83
80
  git(context.repo, "worktree", "add", ...creationArgs);
84
81
  return {
85
82
  path: destination,
86
- name: directoryName,
83
+ name,
87
84
  branch: name,
88
85
  created: true,
89
86
  };
@@ -92,7 +89,7 @@ async function createWorkspace(context, name, base, noFetch, options = {}) {
92
89
  export async function main(argv) {
93
90
  const separator = argv.indexOf("--");
94
91
  const forwarded = separator < 0 ? [] : argv.slice(separator + 1);
95
- const { values, positionals } = args(separator < 0 ? argv : argv.slice(0, separator), [...contextOptions, "base", "branch", "workspace", "agent", "output-path"], ["create", "no-fetch", "setup", "dry-run"], { create: "c", base: "b" });
92
+ const { values, positionals } = args(separator < 0 ? argv : argv.slice(0, separator), [...contextOptions, "base", "workspace", "agent", "output-path"], ["create", "no-fetch", "setup", "dry-run"], { create: "c", base: "b" });
96
93
  const context = commandContext(values);
97
94
  const [command, ...names] = positionals;
98
95
  const allowedOptions = COMMAND_OPTIONS[command];
@@ -101,10 +98,8 @@ export async function main(argv) {
101
98
  for (const option of Object.keys(values))
102
99
  if (!contextOptions.includes(option) && !allowedOptions.includes(option))
103
100
  throw new Error(`--${option} is not supported by rl ${command}`);
104
- if (command === "switch" &&
105
- !values.create &&
106
- (values.base || values["no-fetch"]))
107
- throw new Error("--base and --no-fetch require --create with rl switch");
101
+ if (command === "switch" && !values.create && values.base)
102
+ throw new Error("--base requires --create with rl switch");
108
103
  const selector = typeof values.workspace === "string" ? values.workspace : undefined;
109
104
  if (forwarded.length &&
110
105
  command !== "exec" &&
@@ -132,7 +127,7 @@ export async function main(argv) {
132
127
  console.log(file);
133
128
  }
134
129
  else
135
- throw new Error("Usage: rl config show|init");
130
+ throw new Error("Usage: rl setup show|init");
136
131
  return 0;
137
132
  }
138
133
  if (command === "exec") {
@@ -159,35 +154,26 @@ export async function main(argv) {
159
154
  });
160
155
  });
161
156
  }
162
- if (!["switch", "new", "open"].includes(command))
163
- throw new Error("Unknown workspace workflow command");
164
- arity(names, command === "open" ? 0 : 1);
165
- const selectedBranch = values.branch ?? (command === "open" ? values.base : undefined);
166
- if (command === "open" && typeof selectedBranch !== "string")
167
- throw new Error("Usage: rl open --branch <branch>");
157
+ arity(names, 1);
168
158
  const agent = typeof values.agent === "string" ? values.agent : undefined;
169
159
  if (agent && !SUPPORTED_AGENTS.has(agent))
170
160
  throw new Error("Agent must be codex or claude");
171
- const base = command !== "open" && typeof values.base === "string"
172
- ? values.base
173
- : context.defaultBase;
174
- const creating = !!values.create || command === "new" || command === "open";
175
- const branch = typeof selectedBranch === "string"
176
- ? selectedBranch.replace(/^origin\//, "")
177
- : names[0];
178
- const target = creating
179
- ? await createWorkspace(context, branch, base, !!values["no-fetch"], command === "switch"
180
- ? {}
181
- : {
182
- reuseExisting: true,
183
- ...(command === "open"
184
- ? {
185
- directoryName: branch.replaceAll("/", "-"),
186
- requireBranch: true,
187
- }
188
- : {}),
189
- })
190
- : resolveWorkspace(context, names[0]);
161
+ const base = typeof values.base === "string" ? values.base : context.defaultBase;
162
+ let target;
163
+ if (values.create) {
164
+ target = await createWorkspace(context, names[0], base, !!values["no-fetch"]);
165
+ }
166
+ else {
167
+ try {
168
+ target = resolveWorkspace(context, names[0]);
169
+ }
170
+ catch (error) {
171
+ if (!(error instanceof Error) ||
172
+ !error.message.startsWith("Workspace not found:"))
173
+ throw error;
174
+ target = await createWorkspace(context, names[0].replace(/^origin\//, ""), base, !!values["no-fetch"], { reuseExisting: true, requireBranch: true });
175
+ }
176
+ }
191
177
  await context.store.adopt(target.path, base);
192
178
  if (values.setup) {
193
179
  const code = await locked(path.join(context.store.root, SETUP_LOCK), LOCK_FILE, () => {
package/lib/entry.zsh ADDED
@@ -0,0 +1,54 @@
1
+ #!/bin/zsh -f
2
+ emulate -L zsh
3
+ readonly rl_home="${${(%):-%x}:A:h:h}"
4
+ if [[ "$1" == __hook ]]; then
5
+ # Hooks resolve the installed CLI on PATH, not a version-specific package path.
6
+ # Their explicit repository/state arguments must not be replaced by user config.
7
+ shift
8
+ exec node "$rl_home/dist/cli.js" state "$@"
9
+ fi
10
+ if [[ "$1" == --version || "$1" == -V ]]; then
11
+ exec node -p 'JSON.parse(require("node:fs").readFileSync(process.argv[1], "utf8")).version' "$rl_home/package.json"
12
+ fi
13
+ if [[ "$1" == setup && "$2" == shell ]]; then
14
+ if (( $# == 2 )); then
15
+ exec node "$rl_home/dist/help.js" setup shell
16
+ fi
17
+ for argument in "$@"; do
18
+ [[ "$argument" == -- ]] && break
19
+ if [[ "$argument" == --help || "$argument" == -h ]]; then
20
+ exec node "$rl_home/dist/help.js" "$@"
21
+ fi
22
+ done
23
+ if [[ "$3" != zsh && "$3" != bash || $# != 3 ]]; then
24
+ print -u2 'Usage: rl setup shell <zsh|bash>'
25
+ exit 1
26
+ fi
27
+ if [[ "$3" == zsh ]]; then
28
+ print -r -- "source ${(q)rl_home}/shell/rl.zsh"
29
+ else
30
+ print -r -- "_rl_executable=${(qq)rl_home}/bin/rl"
31
+ cat <<'BASH'
32
+ rl() {
33
+ local destination_file destination result previous="$PWD"
34
+ local -a arguments=("$@")
35
+ if [[ "$1" == switch && "${2:-}" == - ]]; then
36
+ [[ -n "${RL_PREVIOUS_WORKSPACE:-}" ]] || { printf '%s\n' 'No previous workspace in this shell' >&2; return 1; }
37
+ arguments[1]="$RL_PREVIOUS_WORKSPACE"
38
+ fi
39
+ destination_file=$(mktemp "${TMPDIR:-/tmp}/rl-shell.XXXXXXXX") || return 1
40
+ if RL_SHELL_OUTPUT="$destination_file" command "$_rl_executable" "${arguments[@]}"; then result=0; else result=$?; fi
41
+ destination=$(cat -- "$destination_file")
42
+ rm -f -- "$destination_file"
43
+ if [[ -n "$destination" ]]; then
44
+ builtin cd -- "$destination" || return 1
45
+ RL_PREVIOUS_WORKSPACE="$previous"
46
+ fi
47
+ return "$result"
48
+ }
49
+ BASH
50
+ fi
51
+ exit 0
52
+ fi
53
+ source "$rl_home/lib/rl.zsh" || exit 1
54
+ _rl_main "$@"
package/lib/rl.zsh CHANGED
@@ -24,6 +24,12 @@ _rl_change_directory() {
24
24
  print -rn -- "$PWD" > "$RL_SHELL_OUTPUT"
25
25
  else
26
26
  print -r -- "$PWD"
27
+ if [[ -t 1 && -t 2 ]]; then
28
+ case "${SHELL:t}" in
29
+ zsh|bash) print -u2 -r -- "Enable directory switching: eval \"\$(rl setup shell ${SHELL:t})\"" ;;
30
+ *) print -u2 'Enable directory switching with shell integration: rl help setup shell' ;;
31
+ esac
32
+ fi
27
33
  fi
28
34
  }
29
35
 
@@ -57,12 +63,12 @@ _rl_main() {
57
63
  return
58
64
  fi
59
65
  done
60
- if (( ${#help_args} == 1 )) && [[ "$help_args[1]" == (agent|workflow|policy|repo|git|notes|session|config|step) ]]; then
66
+ if (( ${#help_args} == 1 )) && [[ "$help_args[1]" == (agent|workflow|policy|repo|git|notes) ]]; then
61
67
  _rl_help "${help_args[@]}"
62
68
  return
63
69
  fi
64
70
 
65
- # Canonical command families; older spellings remain compatibility aliases.
71
+ # Translate public command families to their internal handlers.
66
72
  # Preserve a leading repository selector while normalizing the public command.
67
73
  local -a routing_prefix=()
68
74
  if [[ "$1" == --repo ]]; then
@@ -72,9 +78,24 @@ _rl_main() {
72
78
  routing_prefix=("$1")
73
79
  shift
74
80
  fi
81
+ case "$1" in
82
+ new|open|instances|merge|clean|summary|handoff|mcp|session|context|progress|config|adopt|init)
83
+ print -u2 -r -- "Unknown command: $1"
84
+ print -u2 'Run rl help for available commands.'
85
+ return 1 ;;
86
+ status)
87
+ if (( ${argv[(Ie)--all]} || ${argv[(Ie)--list]} )); then
88
+ print -u2 'Use rl list for workspace overviews.'
89
+ return 1
90
+ fi ;;
91
+ esac
75
92
  case "$1:$2" in
76
- git:commit|git:rebase|git:squash) argv=(step "$2" "${@:3}") ;;
77
- git:diff|git:log|git:merge) argv=("$2" "${@:3}") ;;
93
+ setup:dependencies|setup:install)
94
+ local setup_module=dependencies
95
+ [[ "$2" == install ]] && setup_module=install
96
+ command node "${${functions_source[_rl_main]}:A:h:h}/dist/$setup_module.js" "${@:3}"
97
+ return ;;
98
+ git:merge) argv=("$2" "${@:3}") ;;
78
99
  agent:sessions) argv=(session list "${@:3}") ;;
79
100
  agent:save) argv=(session save "${@:3}") ;;
80
101
  agent:handoff) argv=(handoff "${@:3}") ;;
@@ -82,9 +103,10 @@ _rl_main() {
82
103
  storage:clean) argv=(clean "${@:3}") ;;
83
104
  setup:init|setup:show) argv=(config "$2" "${@:3}") ;;
84
105
  setup:adopt) argv=(adopt "${@:3}") ;;
106
+ setup:mcp) argv=(mcp-setup "${@:3}") ;;
85
107
  setup:run) argv=(setup "${@:3}") ;;
86
108
  setup:shell)
87
- command "${${functions_source[_rl_main]}:A:h:h}/bin/rl" init "${@:3}"
109
+ command "${${functions_source[_rl_main]}:A:h:h}/bin/rl" setup shell "${@:3}"
88
110
  return ;;
89
111
  notes:summary) argv=(summary "${@:3}") ;;
90
112
  notes:show|notes:path|notes:set|notes:append)
@@ -210,13 +232,19 @@ _rl_main() {
210
232
  --default-base "$default_base" "$@"
211
233
  return
212
234
  fi
213
- if [[ "$command" == pr && ( "$2" == checks || "$2" == checkout ) ]]; then
235
+ if [[ "$command" == pr && "$2" == checkout ]]; then
214
236
  command node "${${functions_source[_rl_main]}:A:h:h}/dist/cli.js" pr \
215
237
  --repo "$repo_root" --state-dir "$state_dir" --base-dir "$base_dir/$repo_name" \
216
238
  --default-base "$default_base" "$@"
217
239
  return
218
240
  fi
219
241
  case "$command" in
242
+ mcp-setup)
243
+ shift
244
+ command node "${${functions_source[_rl_main]}:A:h:h}/dist/cli.js" mcp-setup \
245
+ --repo "$repo_root" --state-dir "$state_dir" --base-dir "$base_dir/$repo_name" \
246
+ --default-base "$default_base" "$@"
247
+ return ;;
220
248
  storage|clean)
221
249
  command node "${${functions_source[_rl_main]}:A:h:h}/dist/cli.js" storage \
222
250
  --repo "$repo_root" --state-dir "$state_dir" --base-dir "$base_dir/$repo_name" \
@@ -227,7 +255,7 @@ _rl_main() {
227
255
  --repo "$repo_root" --state-dir "$state_dir" --base-dir "$base_dir/$repo_name" \
228
256
  --default-base "$default_base" "$@"
229
257
  return ;;
230
- step|merge|diff|log)
258
+ merge)
231
259
  command node "${${functions_source[_rl_main]}:A:h:h}/dist/cli.js" git \
232
260
  --repo "$repo_root" --state-dir "$state_dir" --base-dir "$base_dir/$repo_name" \
233
261
  --default-base "$default_base" "$@"
@@ -261,13 +289,13 @@ _rl_main() {
261
289
  command node "${${functions_source[_rl_main]}:A:h:h}/dist/cli.js" summary \
262
290
  --repo "$repo_root" --state-dir "$state_dir" --default-base "$default_base" "$@"
263
291
  return ;;
264
- adopt|doctor|status|instances|resume|session|context|progress|pr)
292
+ adopt|doctor|status|resume|session|context|progress|pr)
265
293
  _rl_state "$@"
266
294
  return ;;
267
295
  esac
268
296
 
269
297
  case "$command" in
270
- switch|new|open|continue)
298
+ switch|continue)
271
299
  if [[ "$command" == switch && "$2" == - ]]; then
272
300
  [[ -n "${RL_PREVIOUS_WORKSPACE:-}" ]] || { print -u2 'No previous workspace in this shell'; return 1; }
273
301
  argv[2]="$RL_PREVIOUS_WORKSPACE"
@@ -0,0 +1,108 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
+
5
+ <a name="4.1.2"></a>
6
+ ## [4.1.2](https://github.com/moxystudio/node-proper-lockfile/compare/v4.1.1...v4.1.2) (2021-01-25)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * fix node 14 updating graceful-fs ([#102](https://github.com/moxystudio/node-proper-lockfile/issues/102)) ([b0d988e](https://github.com/moxystudio/node-proper-lockfile/commit/b0d988e))
12
+
13
+
14
+
15
+ <a name="4.1.1"></a>
16
+ ## [4.1.1](https://github.com/moxystudio/node-proper-lockfile/compare/v4.1.0...v4.1.1) (2019-04-03)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * fix mtime precision on some filesystems ([#88](https://github.com/moxystudio/node-proper-lockfile/issues/88)) ([f266158](https://github.com/moxystudio/node-proper-lockfile/commit/f266158)), closes [#82](https://github.com/moxystudio/node-proper-lockfile/issues/82) [#87](https://github.com/moxystudio/node-proper-lockfile/issues/87)
22
+
23
+
24
+
25
+ <a name="4.1.0"></a>
26
+ # [4.1.0](https://github.com/moxystudio/node-proper-lockfile/compare/v4.0.0...v4.1.0) (2019-03-18)
27
+
28
+
29
+ ### Features
30
+
31
+ * allow second precision in mtime comparison ([#78](https://github.com/moxystudio/node-proper-lockfile/issues/78)) ([b2816a6](https://github.com/moxystudio/node-proper-lockfile/commit/b2816a6))
32
+
33
+
34
+
35
+ <a name="4.0.0"></a>
36
+ # [4.0.0](https://github.com/moxystudio/node-proper-lockfile/compare/v3.2.0...v4.0.0) (2019-03-12)
37
+
38
+
39
+ ### Bug Fixes
40
+
41
+ * fix typo in error message ([#68](https://github.com/moxystudio/node-proper-lockfile/issues/68)) ([b91cb55](https://github.com/moxystudio/node-proper-lockfile/commit/b91cb55))
42
+
43
+
44
+ ### Features
45
+
46
+ * make staleness check more robust ([#74](https://github.com/moxystudio/node-proper-lockfile/issues/74)) ([9cc0973](https://github.com/moxystudio/node-proper-lockfile/commit/9cc0973)), closes [#71](https://github.com/moxystudio/node-proper-lockfile/issues/71) [/github.com/ipfs/js-ipfs-repo/issues/188#issuecomment-468682971](https://github.com//github.com/ipfs/js-ipfs-repo/issues/188/issues/issuecomment-468682971)
47
+
48
+
49
+ ### BREAKING CHANGES
50
+
51
+ * We were marking the lock as compromised when system went into sleep or if the event loop was busy taking too long to run the internals timers, Now we keep track of the mtime updated by the current process, and if we lose some cycles in the update process but recover and the mtime is still ours we do not mark the lock as compromised.
52
+
53
+
54
+
55
+ <a name="3.2.0"></a>
56
+ # [3.2.0](https://github.com/moxystudio/node-proper-lockfile/compare/v3.1.0...v3.2.0) (2018-11-19)
57
+
58
+
59
+ ### Features
60
+
61
+ * add lock path option ([#66](https://github.com/moxystudio/node-proper-lockfile/issues/66)) ([32f1b8d](https://github.com/moxystudio/node-proper-lockfile/commit/32f1b8d))
62
+
63
+
64
+
65
+ <a name="3.1.0"></a>
66
+ # [3.1.0](https://github.com/moxystudio/node-proper-lockfile/compare/v3.0.2...v3.1.0) (2018-11-15)
67
+
68
+
69
+ ### Bug Fixes
70
+
71
+ * **package:** update retry to version 0.12.0 ([#50](https://github.com/moxystudio/node-proper-lockfile/issues/50)) ([d400b98](https://github.com/moxystudio/node-proper-lockfile/commit/d400b98))
72
+
73
+
74
+ ### Features
75
+
76
+ * add signal exit ([#65](https://github.com/moxystudio/node-proper-lockfile/issues/65)) ([f20bc45](https://github.com/moxystudio/node-proper-lockfile/commit/f20bc45))
77
+
78
+
79
+
80
+ <a name="3.0.2"></a>
81
+ ## [3.0.2](https://github.com/moxystudio/node-proper-lockfile/compare/v3.0.1...v3.0.2) (2018-01-30)
82
+
83
+
84
+
85
+ <a name="3.0.1"></a>
86
+ ## [3.0.1](https://github.com/moxystudio/node-proper-lockfile/compare/v3.0.0...v3.0.1) (2018-01-20)
87
+
88
+
89
+ ### Bug Fixes
90
+
91
+ * restore ability to use lockfile() directly ([0ef8fbc](https://github.com/moxystudio/node-proper-lockfile/commit/0ef8fbc))
92
+
93
+
94
+
95
+ <a name="3.0.0"></a>
96
+ # [3.0.0](https://github.com/moxystudio/node-proper-lockfile/compare/v2.0.1...v3.0.0) (2018-01-20)
97
+
98
+
99
+ ### Chores
100
+
101
+ * update project to latest node lts ([b1d43e5](https://github.com/moxystudio/node-proper-lockfile/commit/b1d43e5))
102
+
103
+
104
+ ### BREAKING CHANGES
105
+
106
+ * remove callback support
107
+ * use of node lts language features such as object spread
108
+ * compromised function in lock() has been moved to an option
@@ -0,0 +1,24 @@
1
+ Copyright (c) Squirrel Chat et al., All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions are met:
5
+
6
+ 1. Redistributions of source code must retain the above copyright notice, this
7
+ list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright notice,
9
+ this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+ 3. Neither the name of the copyright holder nor the names of its contributors
12
+ may be used to endorse or promote products derived from this software without
13
+ specific prior written permission.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.