Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,38 @@ For example:
-- exists: my_schema.c
```

### `layer`

You can organize files into layers that enforce ordering constraints. Files in lower-index layers cannot depend on files in higher-index layers.

For example:

```postgresql
-- name: my_schema.setup
-- layer: first

-- name: my_schema.functions
-- layer: second
-- requires: my_schema.setup

-- name: my_schema.views
-- layer: third
-- requires: my_schema.functions
```

#### Layer Configuration

- Use `--layers first,second,third` to define custom layers in order
- Use `--fallback-layer second` to specify the default layer for files without explicit layer declarations
- Default layers are `prepend,normal,append` with `normal` as the fallback

#### Backward Compatibility

The legacy `-- is_initial` and `-- is_final` headers are still supported:
- `-- is_initial` maps to the "prepend" layer
- `-- is_final` maps to the "append" layer
- Files without layer declarations use the fallback layer

## Example

Lets say you have a directory with the following files:
Expand Down
2 changes: 2 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ pub struct Config<'a> {
pub exclude_node_prefixes: Option<&'a [String]>,
pub include_hidden: bool,
pub subdir_filter: Option<PathBuf>,
pub layers: Vec<String>,
pub fallback_layer: String,
}
39 changes: 28 additions & 11 deletions src/exceptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,27 @@ impl fmt::Display for TopCatError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::GraphMissing => write!(f, "Graph is None"),
Self::InvalidFileHeader(x, s) => write!(f, "Invalid file header in {}: {}", x.display(), s),
Self::NameClash(name, f1, f2) => write!(f, "Name {} found in both {} and {}", name, f1.display(), f2.display()),
Self::MissingExist(x, s) => write!(f, "MissingExist: {} expects {} to exist but it is not found", x, s),
Self::MissingDependency(x, s) => write!(f, "MissingDependency: {} depends on {} but it is missing", x, s),
Self::InvalidDependency(x, s) => write!(f, "InvalidDependency: {} is marked as prepend so it cannot depend on {} which isn't marked as prepend", s, x),
Self::InvalidFileHeader(x, s) => {
write!(f, "Invalid file header in {}: {}", x.display(), s)
}
Self::NameClash(name, f1, f2) => write!(
f,
"Name {} found in both {} and {}",
name,
f1.display(),
f2.display()
),
Self::MissingExist(x, s) => write!(
f,
"MissingExist: {} expects {} to exist but it is not found",
x, s
),
Self::MissingDependency(x, s) => write!(
f,
"MissingDependency: {} depends on {} but it is missing",
x, s
),
Self::InvalidDependency(x, s) => write!(f, "InvalidDependency: {}: {}", x, s),
Self::CyclicDependency(x) => {
let mut error_message = "Cyclic dependency detected:\n".to_string();
for (i, cycle) in x.iter().enumerate() {
Expand All @@ -42,16 +58,13 @@ impl fmt::Display for TopCatError {
error_message.push_str(" Edges:\n");
for (i, node) in cycle.iter().enumerate() {
let next_node = &cycle[(i + 1) % cycle.len()];
error_message.push_str(&format!(
" - {} -> {}\n",
node.name,
next_node.name
));
error_message
.push_str(&format!(" - {} -> {}\n", node.name, next_node.name));
}
}

write!(f, "{}", error_message)
},
}
Self::Io(err) => write!(f, "IO error: {}", err),
Self::UnknownError(s) => write!(f, "UnknownError: {}", s),
}
Expand All @@ -70,6 +83,7 @@ impl Error for TopCatError {}
pub enum FileNodeError {
TooManyNames(PathBuf, Vec<String>),
NoNameDefined(PathBuf),
InvalidLayer(PathBuf, String),
}

impl fmt::Display for FileNodeError {
Expand All @@ -82,6 +96,9 @@ impl fmt::Display for FileNodeError {
s.join(", ")
),
Self::NoNameDefined(x) => write!(f, "No name defined in {}", x.display()),
Self::InvalidLayer(x, layer) => {
write!(f, "Invalid layer '{}' declared in {}", layer, x.display())
}
}
}
}
Expand Down
Loading
Loading