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)
| 3825 | /// (e.g. a GitHub squash-merge message quoting the original commit) do NOT |
| 3826 | /// match: those commits may carry conflict resolutions and must be imported. |
| 3827 | fn parse_push_trailer(message: &str) -> Option<PushTrailer> { |
| 3828 | let last_paragraph = message.trim_end().rsplit("\n\n").next()?; |
| 3829 | |
| 3830 | let mut view = None; |
| 3831 | let mut state = None; |
| 3832 | for line in last_paragraph.lines() { |
| 3833 | let line = line.trim(); |
| 3834 | if let Some(value) = line.strip_prefix("Atomic-View:") { |
| 3835 | view = Some(value.trim().to_string()); |
| 3836 | } else if let Some(value) = line.strip_prefix("Atomic-State:") { |
| 3837 | state = Merkle::from_base32(value.trim().as_bytes()); |
| 3838 | } else if line.starts_with("Atomic-Changes:") { |
| 3839 | // Optional trailer; not needed for self-push detection. |
| 3840 | } else { |
| 3841 | // Non-trailer content in the final paragraph — not a commit |
| 3842 | // produced by `atomic git push`. |
| 3843 | return None; |
| 3844 | } |
| 3845 | } |
| 3846 | |
| 3847 | Some(PushTrailer { |
| 3848 | view: view?, |
| 3849 | state: state?, |
| 3850 | }) |
| 3851 | } |
| 3852 | |
| 3853 | /// Extract metadata from a git commit. |
| 3854 | fn extract_commit_metadata(commit: &git2::Commit) -> CliResult<CommitMetadata> { |