Parse `atomic git push` trailers from a commit message. Only matches when the trailers form the message's final paragraph — the shape `atomic git push` itself produces. Trailer lines embedded mid-body (e.g. a GitHub squash-merge message quoting the original commit) do NOT match: those commits may carry conflict resolutions and must be imported.
(message: &str)
| 3855 | /// (e.g. a GitHub squash-merge message quoting the original commit) do NOT |
| 3856 | /// match: those commits may carry conflict resolutions and must be imported. |
| 3857 | fn parse_push_trailer(message: &str) -> Option<PushTrailer> { |
| 3858 | let last_paragraph = message.trim_end().rsplit("\n\n").next()?; |
| 3859 | |
| 3860 | let mut view = None; |
| 3861 | let mut state = None; |
| 3862 | for line in last_paragraph.lines() { |
| 3863 | let line = line.trim(); |
| 3864 | if let Some(value) = line.strip_prefix("Atomic-View:") { |
| 3865 | view = Some(value.trim().to_string()); |
| 3866 | } else if let Some(value) = line.strip_prefix("Atomic-State:") { |
| 3867 | state = Merkle::from_base32(value.trim().as_bytes()); |
| 3868 | } else if line.starts_with("Atomic-Changes:") { |
| 3869 | // Optional trailer; not needed for self-push detection. |
| 3870 | } else { |
| 3871 | // Non-trailer content in the final paragraph — not a commit |
| 3872 | // produced by `atomic git push`. |
| 3873 | return None; |
| 3874 | } |
| 3875 | } |
| 3876 | |
| 3877 | Some(PushTrailer { |
| 3878 | view: view?, |
| 3879 | state: state?, |
| 3880 | }) |
| 3881 | } |
| 3882 | |
| 3883 | /// Extract metadata from a git commit. |
| 3884 | fn extract_commit_metadata(commit: &git2::Commit) -> CliResult<CommitMetadata> { |