Add git blame (#8889)
This adds a new action to the editor: `editor: toggle git blame`. When used it turns on a sidebar containing `git blame` information for the currently open buffer. The git blame information is updated when the buffer changes. It handles additions, deletions, modifications, changes to the underlying git data (new commits, changed commits, ...), file saves. It also handles folding and wrapping lines correctly. When the user hovers over a commit, a tooltip displays information for the commit that introduced the line. If the repository has a remote with the name `origin` configured, then clicking on a blame entry opens the permalink to the commit on the code host. Users can right-click on a blame entry to get a context menu which allows them to copy the SHA of the commit. The feature also works on shared projects, e.g. when collaborating a peer can request `git blame` data. As of this PR, Zed now comes bundled with a `git` binary so that users don't have to have `git` installed locally to use this feature. ### Screenshots    ### TODOs - [x] Bundling `git` binary ### Release Notes Release Notes: - Added `editor: toggle git blame` command that toggles a sidebar with git blame information for the current buffer. --------- Co-authored-by: Antonio <antonio@zed.dev> Co-authored-by: Piotr <piotr@zed.dev> Co-authored-by: Bennet <bennetbo@gmx.de> Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
co-authored by
Antonio
Piotr
Bennet
Mikayla
parent
e2d6b0deba
commit
7f54935324
@@ -12,16 +12,23 @@ workspace = true
|
||||
path = "src/git.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
clock.workspace = true
|
||||
collections.workspace = true
|
||||
git2.workspace = true
|
||||
lazy_static.workspace = true
|
||||
log.workspace = true
|
||||
smol.workspace = true
|
||||
sum_tree.workspace = true
|
||||
text.workspace = true
|
||||
time.workspace = true
|
||||
url.workspace = true
|
||||
serde.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
unindent.workspace = true
|
||||
serde_json.workspace = true
|
||||
pretty_assertions.workspace = true
|
||||
|
||||
[features]
|
||||
test-support = []
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
use crate::commit::get_messages;
|
||||
use crate::permalink::{build_commit_permalink, parse_git_remote_url, BuildCommitPermalinkParams};
|
||||
use crate::Oid;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use collections::{HashMap, HashSet};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::Write;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::{ops::Range, path::Path};
|
||||
use text::Rope;
|
||||
use time;
|
||||
use time::macros::format_description;
|
||||
use time::OffsetDateTime;
|
||||
use time::UtcOffset;
|
||||
use url::Url;
|
||||
|
||||
pub use git2 as libgit;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Blame {
|
||||
pub entries: Vec<BlameEntry>,
|
||||
pub messages: HashMap<Oid, String>,
|
||||
pub permalinks: HashMap<Oid, Url>,
|
||||
}
|
||||
|
||||
impl Blame {
|
||||
pub fn for_path(
|
||||
git_binary: &Path,
|
||||
working_directory: &Path,
|
||||
path: &Path,
|
||||
content: &Rope,
|
||||
remote_url: Option<String>,
|
||||
) -> Result<Self> {
|
||||
let output = run_git_blame(git_binary, working_directory, path, &content)?;
|
||||
let mut entries = parse_git_blame(&output)?;
|
||||
entries.sort_unstable_by(|a, b| a.range.start.cmp(&b.range.start));
|
||||
|
||||
let mut permalinks = HashMap::default();
|
||||
let mut unique_shas = HashSet::default();
|
||||
let parsed_remote_url = remote_url.as_deref().and_then(parse_git_remote_url);
|
||||
|
||||
for entry in entries.iter_mut() {
|
||||
unique_shas.insert(entry.sha);
|
||||
if let Some(remote) = parsed_remote_url.as_ref() {
|
||||
permalinks.entry(entry.sha).or_insert_with(|| {
|
||||
build_commit_permalink(BuildCommitPermalinkParams {
|
||||
remote,
|
||||
sha: entry.sha.to_string().as_str(),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let shas = unique_shas.into_iter().collect::<Vec<_>>();
|
||||
let messages =
|
||||
get_messages(&working_directory, &shas).context("failed to get commit messages")?;
|
||||
|
||||
Ok(Self {
|
||||
entries,
|
||||
permalinks,
|
||||
messages,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn run_git_blame(
|
||||
git_binary: &Path,
|
||||
working_directory: &Path,
|
||||
path: &Path,
|
||||
contents: &Rope,
|
||||
) -> Result<String> {
|
||||
let child = Command::new(git_binary)
|
||||
.current_dir(working_directory)
|
||||
.arg("blame")
|
||||
.arg("--incremental")
|
||||
.arg("--contents")
|
||||
.arg("-")
|
||||
.arg(path.as_os_str())
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.map_err(|e| anyhow!("Failed to start git blame process: {}", e))?;
|
||||
|
||||
let mut stdin = child
|
||||
.stdin
|
||||
.as_ref()
|
||||
.context("failed to get pipe to stdin of git blame command")?;
|
||||
|
||||
for chunk in contents.chunks() {
|
||||
stdin.write_all(chunk.as_bytes())?;
|
||||
}
|
||||
stdin.flush()?;
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.map_err(|e| anyhow!("Failed to read git blame output: {}", e))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
return Err(anyhow!("git blame process failed: {}", stderr));
|
||||
}
|
||||
|
||||
Ok(String::from_utf8(output.stdout)?)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct BlameEntry {
|
||||
pub sha: Oid,
|
||||
|
||||
pub range: Range<u32>,
|
||||
|
||||
pub original_line_number: u32,
|
||||
|
||||
pub author: Option<String>,
|
||||
pub author_mail: Option<String>,
|
||||
pub author_time: Option<i64>,
|
||||
pub author_tz: Option<String>,
|
||||
|
||||
pub committer: Option<String>,
|
||||
pub committer_mail: Option<String>,
|
||||
pub committer_time: Option<i64>,
|
||||
pub committer_tz: Option<String>,
|
||||
|
||||
pub summary: Option<String>,
|
||||
|
||||
pub previous: Option<String>,
|
||||
pub filename: String,
|
||||
}
|
||||
|
||||
impl BlameEntry {
|
||||
// Returns a BlameEntry by parsing the first line of a `git blame --incremental`
|
||||
// entry. The line MUST have this format:
|
||||
//
|
||||
// <40-byte-hex-sha1> <sourceline> <resultline> <num-lines>
|
||||
fn new_from_blame_line(line: &str) -> Result<BlameEntry> {
|
||||
let mut parts = line.split_whitespace();
|
||||
|
||||
let sha = parts
|
||||
.next()
|
||||
.and_then(|line| line.parse::<Oid>().ok())
|
||||
.ok_or_else(|| anyhow!("failed to parse sha"))?;
|
||||
|
||||
let original_line_number = parts
|
||||
.next()
|
||||
.and_then(|line| line.parse::<u32>().ok())
|
||||
.ok_or_else(|| anyhow!("Failed to parse original line number"))?;
|
||||
let final_line_number = parts
|
||||
.next()
|
||||
.and_then(|line| line.parse::<u32>().ok())
|
||||
.ok_or_else(|| anyhow!("Failed to parse final line number"))?;
|
||||
|
||||
let line_count = parts
|
||||
.next()
|
||||
.and_then(|line| line.parse::<u32>().ok())
|
||||
.ok_or_else(|| anyhow!("Failed to parse final line number"))?;
|
||||
|
||||
let start_line = final_line_number.saturating_sub(1);
|
||||
let end_line = start_line + line_count;
|
||||
let range = start_line..end_line;
|
||||
|
||||
Ok(Self {
|
||||
sha,
|
||||
range,
|
||||
original_line_number,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn author_offset_date_time(&self) -> Result<time::OffsetDateTime> {
|
||||
if let (Some(author_time), Some(author_tz)) = (self.author_time, &self.author_tz) {
|
||||
let format = format_description!("[offset_hour][offset_minute]");
|
||||
let offset = UtcOffset::parse(author_tz, &format)?;
|
||||
let date_time_utc = OffsetDateTime::from_unix_timestamp(author_time)?;
|
||||
|
||||
Ok(date_time_utc.to_offset(offset))
|
||||
} else {
|
||||
// Directly return current time in UTC if there's no committer time or timezone
|
||||
Ok(time::OffsetDateTime::now_utc())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse_git_blame parses the output of `git blame --incremental`, which returns
|
||||
// all the blame-entries for a given path incrementally, as it finds them.
|
||||
//
|
||||
// Each entry *always* starts with:
|
||||
//
|
||||
// <40-byte-hex-sha1> <sourceline> <resultline> <num-lines>
|
||||
//
|
||||
// Each entry *always* ends with:
|
||||
//
|
||||
// filename <whitespace-quoted-filename-goes-here>
|
||||
//
|
||||
// Line numbers are 1-indexed.
|
||||
//
|
||||
// A `git blame --incremental` entry looks like this:
|
||||
//
|
||||
// 6ad46b5257ba16d12c5ca9f0d4900320959df7f4 2 2 1
|
||||
// author Joe Schmoe
|
||||
// author-mail <joe.schmoe@example.com>
|
||||
// author-time 1709741400
|
||||
// author-tz +0100
|
||||
// committer Joe Schmoe
|
||||
// committer-mail <joe.schmoe@example.com>
|
||||
// committer-time 1709741400
|
||||
// committer-tz +0100
|
||||
// summary Joe's cool commit
|
||||
// previous 486c2409237a2c627230589e567024a96751d475 index.js
|
||||
// filename index.js
|
||||
//
|
||||
// If the entry has the same SHA as an entry that was already printed then no
|
||||
// signature information is printed:
|
||||
//
|
||||
// 6ad46b5257ba16d12c5ca9f0d4900320959df7f4 3 4 1
|
||||
// previous 486c2409237a2c627230589e567024a96751d475 index.js
|
||||
// filename index.js
|
||||
//
|
||||
// More about `--incremental` output: https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-blame.html
|
||||
fn parse_git_blame(output: &str) -> Result<Vec<BlameEntry>> {
|
||||
let mut entries: Vec<BlameEntry> = Vec::new();
|
||||
let mut index: HashMap<Oid, usize> = HashMap::default();
|
||||
|
||||
let mut current_entry: Option<BlameEntry> = None;
|
||||
|
||||
for line in output.lines() {
|
||||
let mut done = false;
|
||||
|
||||
match &mut current_entry {
|
||||
None => {
|
||||
let mut new_entry = BlameEntry::new_from_blame_line(line)?;
|
||||
|
||||
if let Some(existing_entry) = index
|
||||
.get(&new_entry.sha)
|
||||
.and_then(|slot| entries.get(*slot))
|
||||
{
|
||||
new_entry.author = existing_entry.author.clone();
|
||||
new_entry.author_mail = existing_entry.author_mail.clone();
|
||||
new_entry.author_time = existing_entry.author_time;
|
||||
new_entry.author_tz = existing_entry.author_tz.clone();
|
||||
new_entry.committer = existing_entry.committer.clone();
|
||||
new_entry.committer_mail = existing_entry.committer_mail.clone();
|
||||
new_entry.committer_time = existing_entry.committer_time;
|
||||
new_entry.committer_tz = existing_entry.committer_tz.clone();
|
||||
new_entry.summary = existing_entry.summary.clone();
|
||||
}
|
||||
|
||||
current_entry.replace(new_entry);
|
||||
}
|
||||
Some(entry) => {
|
||||
let Some((key, value)) = line.split_once(' ') else {
|
||||
continue;
|
||||
};
|
||||
let is_committed = !entry.sha.is_zero();
|
||||
match key {
|
||||
"filename" => {
|
||||
entry.filename = value.into();
|
||||
done = true;
|
||||
}
|
||||
"previous" => entry.previous = Some(value.into()),
|
||||
|
||||
"summary" if is_committed => entry.summary = Some(value.into()),
|
||||
"author" if is_committed => entry.author = Some(value.into()),
|
||||
"author-mail" if is_committed => entry.author_mail = Some(value.into()),
|
||||
"author-time" if is_committed => {
|
||||
entry.author_time = Some(value.parse::<i64>()?)
|
||||
}
|
||||
"author-tz" if is_committed => entry.author_tz = Some(value.into()),
|
||||
|
||||
"committer" if is_committed => entry.committer = Some(value.into()),
|
||||
"committer-mail" if is_committed => entry.committer_mail = Some(value.into()),
|
||||
"committer-time" if is_committed => {
|
||||
entry.committer_time = Some(value.parse::<i64>()?)
|
||||
}
|
||||
"committer-tz" if is_committed => entry.committer_tz = Some(value.into()),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if done {
|
||||
if let Some(entry) = current_entry.take() {
|
||||
index.insert(entry.sha, entries.len());
|
||||
|
||||
// We only want annotations that have a commit.
|
||||
if !entry.sha.is_zero() {
|
||||
entries.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::parse_git_blame;
|
||||
use super::BlameEntry;
|
||||
|
||||
fn read_test_data(filename: &str) -> String {
|
||||
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
path.push("test_data");
|
||||
path.push(filename);
|
||||
|
||||
std::fs::read_to_string(&path)
|
||||
.unwrap_or_else(|_| panic!("Could not read test data at {:?}. Is it generated?", path))
|
||||
}
|
||||
|
||||
fn assert_eq_golden(entries: &Vec<BlameEntry>, golden_filename: &str) {
|
||||
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
path.push("test_data");
|
||||
path.push("golden");
|
||||
path.push(format!("{}.json", golden_filename));
|
||||
|
||||
let have_json =
|
||||
serde_json::to_string_pretty(&entries).expect("could not serialize entries to JSON");
|
||||
|
||||
let update = std::env::var("UPDATE_GOLDEN")
|
||||
.map(|val| val.to_ascii_lowercase() == "true")
|
||||
.unwrap_or(false);
|
||||
|
||||
if update {
|
||||
std::fs::create_dir_all(path.parent().unwrap())
|
||||
.expect("could not create golden test data directory");
|
||||
std::fs::write(&path, have_json).expect("could not write out golden data");
|
||||
} else {
|
||||
let want_json =
|
||||
std::fs::read_to_string(&path).unwrap_or_else(|_| {
|
||||
panic!("could not read golden test data file at {:?}. Did you run the test with UPDATE_GOLDEN=true before?", path);
|
||||
});
|
||||
|
||||
pretty_assertions::assert_eq!(have_json, want_json, "wrong blame entries");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_git_blame_not_committed() {
|
||||
let output = read_test_data("blame_incremental_not_committed");
|
||||
let entries = parse_git_blame(&output).unwrap();
|
||||
assert_eq_golden(&entries, "blame_incremental_not_committed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_git_blame_simple() {
|
||||
let output = read_test_data("blame_incremental_simple");
|
||||
let entries = parse_git_blame(&output).unwrap();
|
||||
assert_eq_golden(&entries, "blame_incremental_simple");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_git_blame_complex() {
|
||||
let output = read_test_data("blame_incremental_complex");
|
||||
let entries = parse_git_blame(&output).unwrap();
|
||||
assert_eq_golden(&entries, "blame_incremental_complex");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
use crate::Oid;
|
||||
use anyhow::{anyhow, Result};
|
||||
use collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
pub fn get_messages(working_directory: &Path, shas: &[Oid]) -> Result<HashMap<Oid, String>> {
|
||||
const MARKER: &'static str = "<MARKER>";
|
||||
|
||||
let output = Command::new("git")
|
||||
.current_dir(working_directory)
|
||||
.arg("show")
|
||||
.arg("-s")
|
||||
.arg(format!("--format=%B{}", MARKER))
|
||||
.args(shas.iter().map(ToString::to_string))
|
||||
.output()
|
||||
.map_err(|e| anyhow!("Failed to start git blame process: {}", e))?;
|
||||
|
||||
anyhow::ensure!(
|
||||
output.status.success(),
|
||||
"'git show' failed with error {:?}",
|
||||
output.status
|
||||
);
|
||||
|
||||
Ok(shas
|
||||
.iter()
|
||||
.cloned()
|
||||
.zip(
|
||||
String::from_utf8_lossy(&output.stdout)
|
||||
.trim()
|
||||
.split_terminator(MARKER)
|
||||
.map(|str| String::from(str.trim())),
|
||||
)
|
||||
.collect::<HashMap<Oid, String>>())
|
||||
}
|
||||
@@ -1,11 +1,107 @@
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ffi::OsStr;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub use git2 as libgit;
|
||||
pub use lazy_static::lazy_static;
|
||||
|
||||
pub mod blame;
|
||||
pub mod commit;
|
||||
pub mod diff;
|
||||
pub mod permalink;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref DOT_GIT: &'static OsStr = OsStr::new(".git");
|
||||
pub static ref GITIGNORE: &'static OsStr = OsStr::new(".gitignore");
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub struct Oid(libgit::Oid);
|
||||
|
||||
impl Oid {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
|
||||
let oid = libgit::Oid::from_bytes(bytes).context("failed to parse bytes into git oid")?;
|
||||
Ok(Self(oid))
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
self.0.as_bytes()
|
||||
}
|
||||
|
||||
pub(crate) fn is_zero(&self) -> bool {
|
||||
self.0.is_zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Oid {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(s: &str) -> std::prelude::v1::Result<Self, Self::Err> {
|
||||
libgit::Oid::from_str(s)
|
||||
.map_err(|error| anyhow!("failed to parse git oid: {}", error))
|
||||
.map(|oid| Self(oid))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Oid {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Oid {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Oid {
|
||||
fn serialize<S>(&self, serializer: S) -> std::prelude::v1::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.0.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Oid {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
s.parse::<Oid>().map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Oid {
|
||||
fn default() -> Self {
|
||||
Self(libgit::Oid::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oid> for u32 {
|
||||
fn from(oid: Oid) -> Self {
|
||||
let bytes = oid.0.as_bytes();
|
||||
debug_assert!(bytes.len() > 4);
|
||||
|
||||
let mut u32_bytes: [u8; 4] = [0; 4];
|
||||
u32_bytes.copy_from_slice(&bytes[..4]);
|
||||
|
||||
u32::from_ne_bytes(u32_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oid> for usize {
|
||||
fn from(oid: Oid) -> Self {
|
||||
let bytes = oid.0.as_bytes();
|
||||
debug_assert!(bytes.len() > 8);
|
||||
|
||||
let mut u64_bytes: [u8; 8] = [0; 8];
|
||||
u64_bytes.copy_from_slice(&bytes[..8]);
|
||||
|
||||
u64::from_ne_bytes(u64_bytes) as usize
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,727 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use url::Url;
|
||||
|
||||
pub(crate) enum GitHostingProvider {
|
||||
Github,
|
||||
Gitlab,
|
||||
Gitee,
|
||||
Bitbucket,
|
||||
Sourcehut,
|
||||
Codeberg,
|
||||
}
|
||||
|
||||
impl GitHostingProvider {
|
||||
fn base_url(&self) -> Url {
|
||||
let base_url = match self {
|
||||
Self::Github => "https://github.com",
|
||||
Self::Gitlab => "https://gitlab.com",
|
||||
Self::Gitee => "https://gitee.com",
|
||||
Self::Bitbucket => "https://bitbucket.org",
|
||||
Self::Sourcehut => "https://git.sr.ht",
|
||||
Self::Codeberg => "https://codeberg.org",
|
||||
};
|
||||
|
||||
Url::parse(&base_url).unwrap()
|
||||
}
|
||||
|
||||
/// Returns the fragment portion of the URL for the selected lines in
|
||||
/// the representation the [`GitHostingProvider`] expects.
|
||||
fn line_fragment(&self, selection: &Range<u32>) -> String {
|
||||
if selection.start == selection.end {
|
||||
let line = selection.start + 1;
|
||||
|
||||
match self {
|
||||
Self::Github | Self::Gitlab | Self::Gitee | Self::Sourcehut | Self::Codeberg => {
|
||||
format!("L{}", line)
|
||||
}
|
||||
Self::Bitbucket => format!("lines-{}", line),
|
||||
}
|
||||
} else {
|
||||
let start_line = selection.start + 1;
|
||||
let end_line = selection.end + 1;
|
||||
|
||||
match self {
|
||||
Self::Github | Self::Codeberg => format!("L{}-L{}", start_line, end_line),
|
||||
Self::Gitlab | Self::Gitee | Self::Sourcehut => {
|
||||
format!("L{}-{}", start_line, end_line)
|
||||
}
|
||||
Self::Bitbucket => format!("lines-{}:{}", start_line, end_line),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BuildPermalinkParams<'a> {
|
||||
pub remote_url: &'a str,
|
||||
pub sha: &'a str,
|
||||
pub path: &'a str,
|
||||
pub selection: Option<Range<u32>>,
|
||||
}
|
||||
|
||||
pub fn build_permalink(params: BuildPermalinkParams) -> Result<Url> {
|
||||
let BuildPermalinkParams {
|
||||
remote_url,
|
||||
sha,
|
||||
path,
|
||||
selection,
|
||||
} = params;
|
||||
|
||||
let ParsedGitRemote {
|
||||
provider,
|
||||
owner,
|
||||
repo,
|
||||
} = parse_git_remote_url(remote_url)
|
||||
.ok_or_else(|| anyhow!("failed to parse Git remote URL"))?;
|
||||
|
||||
let path = match provider {
|
||||
GitHostingProvider::Github => format!("{owner}/{repo}/blob/{sha}/{path}"),
|
||||
GitHostingProvider::Gitlab => format!("{owner}/{repo}/-/blob/{sha}/{path}"),
|
||||
GitHostingProvider::Gitee => format!("{owner}/{repo}/blob/{sha}/{path}"),
|
||||
GitHostingProvider::Bitbucket => format!("{owner}/{repo}/src/{sha}/{path}"),
|
||||
GitHostingProvider::Sourcehut => format!("~{owner}/{repo}/tree/{sha}/item/{path}"),
|
||||
GitHostingProvider::Codeberg => format!("{owner}/{repo}/src/commit/{sha}/{path}"),
|
||||
};
|
||||
let line_fragment = selection.map(|selection| provider.line_fragment(&selection));
|
||||
|
||||
let mut permalink = provider.base_url().join(&path).unwrap();
|
||||
permalink.set_fragment(line_fragment.as_deref());
|
||||
Ok(permalink)
|
||||
}
|
||||
|
||||
pub(crate) struct ParsedGitRemote<'a> {
|
||||
pub provider: GitHostingProvider,
|
||||
pub owner: &'a str,
|
||||
pub repo: &'a str,
|
||||
}
|
||||
|
||||
pub(crate) struct BuildCommitPermalinkParams<'a> {
|
||||
pub remote: &'a ParsedGitRemote<'a>,
|
||||
pub sha: &'a str,
|
||||
}
|
||||
|
||||
pub(crate) fn build_commit_permalink(params: BuildCommitPermalinkParams) -> Url {
|
||||
let BuildCommitPermalinkParams { sha, remote } = params;
|
||||
|
||||
let ParsedGitRemote {
|
||||
provider,
|
||||
owner,
|
||||
repo,
|
||||
} = remote;
|
||||
|
||||
let path = match provider {
|
||||
GitHostingProvider::Github => format!("{owner}/{repo}/commits/{sha}"),
|
||||
GitHostingProvider::Gitlab => format!("{owner}/{repo}/-/commit/{sha}"),
|
||||
GitHostingProvider::Gitee => format!("{owner}/{repo}/commit/{sha}"),
|
||||
GitHostingProvider::Bitbucket => format!("{owner}/{repo}/commits/{sha}"),
|
||||
GitHostingProvider::Sourcehut => format!("~{owner}/{repo}/commit/{sha}"),
|
||||
GitHostingProvider::Codeberg => format!("{owner}/{repo}/commit/{sha}"),
|
||||
};
|
||||
|
||||
provider.base_url().join(&path).unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn parse_git_remote_url(url: &str) -> Option<ParsedGitRemote> {
|
||||
if url.starts_with("git@github.com:") || url.starts_with("https://github.com/") {
|
||||
let repo_with_owner = url
|
||||
.trim_start_matches("git@github.com:")
|
||||
.trim_start_matches("https://github.com/")
|
||||
.trim_end_matches(".git");
|
||||
|
||||
let (owner, repo) = repo_with_owner.split_once('/')?;
|
||||
|
||||
return Some(ParsedGitRemote {
|
||||
provider: GitHostingProvider::Github,
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
}
|
||||
|
||||
if url.starts_with("git@gitlab.com:") || url.starts_with("https://gitlab.com/") {
|
||||
let repo_with_owner = url
|
||||
.trim_start_matches("git@gitlab.com:")
|
||||
.trim_start_matches("https://gitlab.com/")
|
||||
.trim_end_matches(".git");
|
||||
|
||||
let (owner, repo) = repo_with_owner.split_once('/')?;
|
||||
|
||||
return Some(ParsedGitRemote {
|
||||
provider: GitHostingProvider::Gitlab,
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
}
|
||||
|
||||
if url.starts_with("git@gitee.com:") || url.starts_with("https://gitee.com/") {
|
||||
let repo_with_owner = url
|
||||
.trim_start_matches("git@gitee.com:")
|
||||
.trim_start_matches("https://gitee.com/")
|
||||
.trim_end_matches(".git");
|
||||
|
||||
let (owner, repo) = repo_with_owner.split_once('/')?;
|
||||
|
||||
return Some(ParsedGitRemote {
|
||||
provider: GitHostingProvider::Gitee,
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
}
|
||||
|
||||
if url.contains("bitbucket.org") {
|
||||
let (_, repo_with_owner) = url.trim_end_matches(".git").split_once("bitbucket.org")?;
|
||||
let (owner, repo) = repo_with_owner
|
||||
.trim_start_matches('/')
|
||||
.trim_start_matches(':')
|
||||
.split_once('/')?;
|
||||
|
||||
return Some(ParsedGitRemote {
|
||||
provider: GitHostingProvider::Bitbucket,
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
}
|
||||
|
||||
if url.starts_with("git@git.sr.ht:") || url.starts_with("https://git.sr.ht/") {
|
||||
// sourcehut indicates a repo with '.git' suffix as a separate repo.
|
||||
// For example, "git@git.sr.ht:~username/repo" and "git@git.sr.ht:~username/repo.git"
|
||||
// are two distinct repositories.
|
||||
let repo_with_owner = url
|
||||
.trim_start_matches("git@git.sr.ht:~")
|
||||
.trim_start_matches("https://git.sr.ht/~");
|
||||
|
||||
let (owner, repo) = repo_with_owner.split_once('/')?;
|
||||
|
||||
return Some(ParsedGitRemote {
|
||||
provider: GitHostingProvider::Sourcehut,
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
}
|
||||
|
||||
if url.starts_with("git@codeberg.org:") || url.starts_with("https://codeberg.org/") {
|
||||
let repo_with_owner = url
|
||||
.trim_start_matches("git@codeberg.org:")
|
||||
.trim_start_matches("https://codeberg.org/")
|
||||
.trim_end_matches(".git");
|
||||
|
||||
let (owner, repo) = repo_with_owner.split_once('/')?;
|
||||
|
||||
return Some(ParsedGitRemote {
|
||||
provider: GitHostingProvider::Codeberg,
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_build_github_permalink_from_ssh_url() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@github.com:zed-industries/zed.git",
|
||||
sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://github.com/zed-industries/zed/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_github_permalink_from_ssh_url_single_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@github.com:zed-industries/zed.git",
|
||||
sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: Some(6..6),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://github.com/zed-industries/zed/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L7";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_github_permalink_from_ssh_url_multi_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@github.com:zed-industries/zed.git",
|
||||
sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: Some(23..47),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://github.com/zed-industries/zed/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L24-L48";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_github_permalink_from_https_url() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://github.com/zed-industries/zed.git",
|
||||
sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://github.com/zed-industries/zed/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_github_permalink_from_https_url_single_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://github.com/zed-industries/zed.git",
|
||||
sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: Some(6..6),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://github.com/zed-industries/zed/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs#L7";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_github_permalink_from_https_url_multi_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://github.com/zed-industries/zed.git",
|
||||
sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: Some(23..47),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://github.com/zed-industries/zed/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs#L24-L48";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_gitlab_permalink_from_ssh_url() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@gitlab.com:zed-industries/zed.git",
|
||||
sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_gitlab_permalink_from_ssh_url_single_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@gitlab.com:zed-industries/zed.git",
|
||||
sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: Some(6..6),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L7";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_gitlab_permalink_from_ssh_url_multi_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@gitlab.com:zed-industries/zed.git",
|
||||
sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: Some(23..47),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L24-48";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_gitlab_permalink_from_https_url() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://gitlab.com/zed-industries/zed.git",
|
||||
sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_gitlab_permalink_from_https_url_single_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://gitlab.com/zed-industries/zed.git",
|
||||
sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: Some(6..6),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs#L7";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_gitlab_permalink_from_https_url_multi_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://gitlab.com/zed-industries/zed.git",
|
||||
sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: Some(23..47),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs#L24-48";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_gitee_permalink_from_ssh_url() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@gitee.com:libkitten/zed.git",
|
||||
sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://gitee.com/libkitten/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_gitee_permalink_from_ssh_url_single_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@gitee.com:libkitten/zed.git",
|
||||
sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: Some(6..6),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://gitee.com/libkitten/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs#L7";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_gitee_permalink_from_ssh_url_multi_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@gitee.com:libkitten/zed.git",
|
||||
sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: Some(23..47),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://gitee.com/libkitten/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs#L24-48";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_gitee_permalink_from_https_url() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://gitee.com/libkitten/zed.git",
|
||||
sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://gitee.com/libkitten/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/zed/src/main.rs";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_gitee_permalink_from_https_url_single_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://gitee.com/libkitten/zed.git",
|
||||
sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: Some(6..6),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://gitee.com/libkitten/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/zed/src/main.rs#L7";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_gitee_permalink_from_https_url_multi_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://gitee.com/libkitten/zed.git",
|
||||
sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: Some(23..47),
|
||||
})
|
||||
.unwrap();
|
||||
let expected_url = "https://gitee.com/libkitten/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/zed/src/main.rs#L24-48";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_git_remote_url_bitbucket_https_with_username() {
|
||||
let url = "https://thorstenballzed@bitbucket.org/thorstenzed/testingrepo.git";
|
||||
let parsed = parse_git_remote_url(url).unwrap();
|
||||
assert!(matches!(parsed.provider, GitHostingProvider::Bitbucket));
|
||||
assert_eq!(parsed.owner, "thorstenzed");
|
||||
assert_eq!(parsed.repo, "testingrepo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_git_remote_url_bitbucket_https_without_username() {
|
||||
let url = "https://bitbucket.org/thorstenzed/testingrepo.git";
|
||||
let parsed = parse_git_remote_url(url).unwrap();
|
||||
assert!(matches!(parsed.provider, GitHostingProvider::Bitbucket));
|
||||
assert_eq!(parsed.owner, "thorstenzed");
|
||||
assert_eq!(parsed.repo, "testingrepo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_git_remote_url_bitbucket_git() {
|
||||
let url = "git@bitbucket.org:thorstenzed/testingrepo.git";
|
||||
let parsed = parse_git_remote_url(url).unwrap();
|
||||
assert!(matches!(parsed.provider, GitHostingProvider::Bitbucket));
|
||||
assert_eq!(parsed.owner, "thorstenzed");
|
||||
assert_eq!(parsed.repo, "testingrepo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_bitbucket_permalink_from_ssh_url() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@bitbucket.org:thorstenzed/testingrepo.git",
|
||||
sha: "f00b4r",
|
||||
path: "main.rs",
|
||||
selection: None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://bitbucket.org/thorstenzed/testingrepo/src/f00b4r/main.rs";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_bitbucket_permalink_from_ssh_url_single_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@bitbucket.org:thorstenzed/testingrepo.git",
|
||||
sha: "f00b4r",
|
||||
path: "main.rs",
|
||||
selection: Some(6..6),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url =
|
||||
"https://bitbucket.org/thorstenzed/testingrepo/src/f00b4r/main.rs#lines-7";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_bitbucket_permalink_from_ssh_url_multi_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@bitbucket.org:thorstenzed/testingrepo.git",
|
||||
sha: "f00b4r",
|
||||
path: "main.rs",
|
||||
selection: Some(23..47),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url =
|
||||
"https://bitbucket.org/thorstenzed/testingrepo/src/f00b4r/main.rs#lines-24:48";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_sourcehut_permalink_from_ssh_url() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@git.sr.ht:~rajveermalviya/zed",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_sourcehut_permalink_from_ssh_url_with_git_prefix() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@git.sr.ht:~rajveermalviya/zed.git",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://git.sr.ht/~rajveermalviya/zed.git/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_sourcehut_permalink_from_ssh_url_single_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@git.sr.ht:~rajveermalviya/zed",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: Some(6..6),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs#L7";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_sourcehut_permalink_from_ssh_url_multi_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@git.sr.ht:~rajveermalviya/zed",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: Some(23..47),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs#L24-48";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_sourcehut_permalink_from_https_url() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://git.sr.ht/~rajveermalviya/zed",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/zed/src/main.rs";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_sourcehut_permalink_from_https_url_single_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://git.sr.ht/~rajveermalviya/zed",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: Some(6..6),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/zed/src/main.rs#L7";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_sourcehut_permalink_from_https_url_multi_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://git.sr.ht/~rajveermalviya/zed",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: Some(23..47),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/zed/src/main.rs#L24-48";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_codeberg_permalink_from_ssh_url() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@codeberg.org:rajveermalviya/zed.git",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://codeberg.org/rajveermalviya/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/editor/src/git/permalink.rs";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_codeberg_permalink_from_ssh_url_single_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@codeberg.org:rajveermalviya/zed.git",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: Some(6..6),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://codeberg.org/rajveermalviya/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/editor/src/git/permalink.rs#L7";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_codeberg_permalink_from_ssh_url_multi_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "git@codeberg.org:rajveermalviya/zed.git",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/editor/src/git/permalink.rs",
|
||||
selection: Some(23..47),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://codeberg.org/rajveermalviya/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/editor/src/git/permalink.rs#L24-L48";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_codeberg_permalink_from_https_url() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://codeberg.org/rajveermalviya/zed.git",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://codeberg.org/rajveermalviya/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/zed/src/main.rs";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_codeberg_permalink_from_https_url_single_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://codeberg.org/rajveermalviya/zed.git",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: Some(6..6),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://codeberg.org/rajveermalviya/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/zed/src/main.rs#L7";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_codeberg_permalink_from_https_url_multi_line_selection() {
|
||||
let permalink = build_permalink(BuildPermalinkParams {
|
||||
remote_url: "https://codeberg.org/rajveermalviya/zed.git",
|
||||
sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
|
||||
path: "crates/zed/src/main.rs",
|
||||
selection: Some(23..47),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_url = "https://codeberg.org/rajveermalviya/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/zed/src/main.rs#L24-L48";
|
||||
assert_eq!(permalink.to_string(), expected_url.to_string())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206 6 6 3
|
||||
author Mahdy M. Karam
|
||||
author-mail <64036912+mmkaram@users.noreply.github.com>
|
||||
author-time 1708621949
|
||||
author-tz -0800
|
||||
committer GitHub
|
||||
committer-mail <noreply@github.com>
|
||||
committer-time 1708621949
|
||||
committer-tz -0700
|
||||
summary Add option to either use system clipboard or vim clipboard (#7936)
|
||||
previous c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206 12 12 2
|
||||
previous c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206 18 18 1
|
||||
previous c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206 21 21 7
|
||||
previous c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206 31 31 1
|
||||
previous c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206 34 34 1
|
||||
previous c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206 86 86 16
|
||||
previous c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
3635d2dcedd83f1b6702f33ca2673317f7fa4695 1 1 2
|
||||
author Conrad Irwin
|
||||
author-mail <conrad@zed.dev>
|
||||
author-time 1707520689
|
||||
author-tz -0700
|
||||
committer GitHub
|
||||
committer-mail <noreply@github.com>
|
||||
committer-time 1707520689
|
||||
committer-tz -0700
|
||||
summary Highlight selections on vim yank (#7638)
|
||||
previous efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
3635d2dcedd83f1b6702f33ca2673317f7fa4695 4 4 1
|
||||
previous efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
3635d2dcedd83f1b6702f33ca2673317f7fa4695 7 10 2
|
||||
previous efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
3635d2dcedd83f1b6702f33ca2673317f7fa4695 10 14 4
|
||||
previous efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
3635d2dcedd83f1b6702f33ca2673317f7fa4695 15 19 2
|
||||
previous efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
3635d2dcedd83f1b6702f33ca2673317f7fa4695 19 28 3
|
||||
previous efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
3635d2dcedd83f1b6702f33ca2673317f7fa4695 22 32 2
|
||||
previous efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
3635d2dcedd83f1b6702f33ca2673317f7fa4695 25 35 2
|
||||
previous efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
3635d2dcedd83f1b6702f33ca2673317f7fa4695 31 41 1
|
||||
previous efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
3635d2dcedd83f1b6702f33ca2673317f7fa4695 57 67 5
|
||||
previous efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
3635d2dcedd83f1b6702f33ca2673317f7fa4695 78 102 18
|
||||
previous efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
b65cf6d2d9576171edb407f5bbaa231c33af1f71 3 5 1
|
||||
author Max Brunsfeld
|
||||
author-mail <maxbrunsfeld@gmail.com>
|
||||
author-time 1705619094
|
||||
author-tz -0800
|
||||
committer Max Brunsfeld
|
||||
committer-mail <maxbrunsfeld@gmail.com>
|
||||
committer-time 1705619205
|
||||
committer-tz -0800
|
||||
summary Merge branch 'main' into language-api-docs
|
||||
previous 6457ccf9ece3b36a37e675783abee9748a443115 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
b65cf6d2d9576171edb407f5bbaa231c33af1f71 51 121 8
|
||||
previous 6457ccf9ece3b36a37e675783abee9748a443115 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
b02bd9bce1db3a68dcd606718fa02709020860af 29 61 1
|
||||
author Conrad Irwin
|
||||
author-mail <conrad@zed.dev>
|
||||
author-time 1694798044
|
||||
author-tz -0600
|
||||
committer Conrad Irwin
|
||||
committer-mail <conrad@zed.dev>
|
||||
committer-time 1694798044
|
||||
committer-tz -0600
|
||||
summary Fix Y on last line with no trailing new line
|
||||
previous 7c77baa7c17eea106330622e70513ea9389d50a1 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
b02bd9bce1db3a68dcd606718fa02709020860af 33 65 1
|
||||
previous 7c77baa7c17eea106330622e70513ea9389d50a1 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
e4794e3134b6449e36ed2771a8849046489cc252 13 45 1
|
||||
author Conrad Irwin
|
||||
author-mail <conrad@zed.dev>
|
||||
author-time 1692855942
|
||||
author-tz -0600
|
||||
committer Conrad Irwin
|
||||
committer-mail <conrad@zed.dev>
|
||||
committer-time 1692856812
|
||||
committer-tz -0600
|
||||
summary vim: Fix linewise copy of last line with no trailing newline
|
||||
previous 26c3312049a9c73bc3350528c1defd3820a7a8c7 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
e4794e3134b6449e36ed2771a8849046489cc252 21 53 8
|
||||
previous 26c3312049a9c73bc3350528c1defd3820a7a8c7 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
e4794e3134b6449e36ed2771a8849046489cc252 29 62 3
|
||||
previous 26c3312049a9c73bc3350528c1defd3820a7a8c7 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
e4794e3134b6449e36ed2771a8849046489cc252 33 66 1
|
||||
previous 26c3312049a9c73bc3350528c1defd3820a7a8c7 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
e4794e3134b6449e36ed2771a8849046489cc252 37 75 3
|
||||
previous 26c3312049a9c73bc3350528c1defd3820a7a8c7 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
33d7fe02ee560f6ed57d1425c43e60aef3b66e64 10 43 1
|
||||
author Conrad Irwin
|
||||
author-mail <conrad@zed.dev>
|
||||
author-time 1692644159
|
||||
author-tz -0600
|
||||
committer Conrad Irwin
|
||||
committer-mail <conrad@zed.dev>
|
||||
committer-time 1692732477
|
||||
committer-tz -0600
|
||||
summary Rewrite paste
|
||||
previous 31db5e4f62e8fca75aa0870f903ae044524c3580 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
33d7fe02ee560f6ed57d1425c43e60aef3b66e64 14 47 6
|
||||
previous 31db5e4f62e8fca75aa0870f903ae044524c3580 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
868c46062008bb0bcab2d41a38b4295996b9b958 20 81 1
|
||||
author Max Brunsfeld
|
||||
author-mail <maxbrunsfeld@gmail.com>
|
||||
author-time 1659072896
|
||||
author-tz -0700
|
||||
committer Max Brunsfeld
|
||||
committer-mail <maxbrunsfeld@gmail.com>
|
||||
committer-time 1659073230
|
||||
committer-tz -0700
|
||||
summary :art: Rename and simplify some autoindent stuff
|
||||
previous 7a26fa18c7fee3fe031b991e18b55fd8f9c4eb1b crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
e93c49f4f02b3edaddae6a6a4cc0ac433f242357 5 37 1
|
||||
author Kaylee Simmons
|
||||
author-mail <kay@the-simmons.net>
|
||||
author-time 1653424557
|
||||
author-tz -0700
|
||||
committer Kaylee Simmons
|
||||
committer-mail <kay@the-simmons.net>
|
||||
committer-time 1653609725
|
||||
committer-tz -0700
|
||||
summary Unify visual line_mode and non line_mode operators
|
||||
previous 11569a869a72f786a9798c53266e28c05c79f824 crates/vim/src/utils.rs
|
||||
filename crates/vim/src/utils.rs
|
||||
082036161fd3815c831ceedfd28ba15b0ed6eb9f 1 3 1
|
||||
author Kaylee Simmons
|
||||
author-mail <kay@the-simmons.net>
|
||||
author-time 1653007350
|
||||
author-tz -0700
|
||||
committer Kaylee Simmons
|
||||
committer-mail <kay@the-simmons.net>
|
||||
committer-time 1653609725
|
||||
committer-tz -0700
|
||||
summary Enable copy and paste in vim mode
|
||||
filename crates/vim/src/utils.rs
|
||||
082036161fd3815c831ceedfd28ba15b0ed6eb9f 4 9 1
|
||||
filename crates/vim/src/utils.rs
|
||||
082036161fd3815c831ceedfd28ba15b0ed6eb9f 7 38 3
|
||||
filename crates/vim/src/utils.rs
|
||||
082036161fd3815c831ceedfd28ba15b0ed6eb9f 10 42 1
|
||||
filename crates/vim/src/utils.rs
|
||||
082036161fd3815c831ceedfd28ba15b0ed6eb9f 11 44 1
|
||||
filename crates/vim/src/utils.rs
|
||||
082036161fd3815c831ceedfd28ba15b0ed6eb9f 14 46 1
|
||||
filename crates/vim/src/utils.rs
|
||||
082036161fd3815c831ceedfd28ba15b0ed6eb9f 15 72 3
|
||||
filename crates/vim/src/utils.rs
|
||||
082036161fd3815c831ceedfd28ba15b0ed6eb9f 18 78 3
|
||||
filename crates/vim/src/utils.rs
|
||||
082036161fd3815c831ceedfd28ba15b0ed6eb9f 21 82 4
|
||||
filename crates/vim/src/utils.rs
|
||||
082036161fd3815c831ceedfd28ba15b0ed6eb9f 26 120 1
|
||||
filename crates/vim/src/utils.rs
|
||||
@@ -0,0 +1,64 @@
|
||||
0000000000000000000000000000000000000000 4 4 3
|
||||
author External file (--contents)
|
||||
author-mail <external.file>
|
||||
author-time 1710764166
|
||||
author-tz +0100
|
||||
committer External file (--contents)
|
||||
committer-mail <external.file>
|
||||
committer-time 1710764166
|
||||
committer-tz +0100
|
||||
summary Version of file_b.txt from file_b_memory.txt
|
||||
previous 4aaba34cb86b12f3a749dd6ddbf185de88de6527 file_b.txt
|
||||
filename file_b.txt
|
||||
0000000000000000000000000000000000000000 10 10 1
|
||||
previous 4aaba34cb86b12f3a749dd6ddbf185de88de6527 file_b.txt
|
||||
filename file_b.txt
|
||||
0000000000000000000000000000000000000000 15 15 2
|
||||
previous 4aaba34cb86b12f3a749dd6ddbf185de88de6527 file_b.txt
|
||||
filename file_b.txt
|
||||
4aaba34cb86b12f3a749dd6ddbf185de88de6527 4 7 2
|
||||
author Thorsten Ball
|
||||
author-mail <mrnugget@gmail.com>
|
||||
author-time 1710764113
|
||||
author-tz +0100
|
||||
committer Thorsten Ball
|
||||
committer-mail <mrnugget@gmail.com>
|
||||
committer-time 1710764113
|
||||
committer-tz +0100
|
||||
summary Another commit
|
||||
previous b2f6b0d982a9e7654bbb6d979c9ccb00b1d2e913 file_b.txt
|
||||
filename file_b.txt
|
||||
4aaba34cb86b12f3a749dd6ddbf185de88de6527 11 17 2
|
||||
previous b2f6b0d982a9e7654bbb6d979c9ccb00b1d2e913 file_b.txt
|
||||
filename file_b.txt
|
||||
b2f6b0d982a9e7654bbb6d979c9ccb00b1d2e913 6 9 1
|
||||
author Thorsten Ball
|
||||
author-mail <mrnugget@gmail.com>
|
||||
author-time 1710764087
|
||||
author-tz +0100
|
||||
committer Thorsten Ball
|
||||
committer-mail <mrnugget@gmail.com>
|
||||
committer-time 1710764087
|
||||
committer-tz +0100
|
||||
summary Another commit
|
||||
previous 7aef8a9a211ebc86824769c89f48e4f64aa6183f file_b.txt
|
||||
filename file_b.txt
|
||||
b2f6b0d982a9e7654bbb6d979c9ccb00b1d2e913 7 11 2
|
||||
previous 7aef8a9a211ebc86824769c89f48e4f64aa6183f file_b.txt
|
||||
filename file_b.txt
|
||||
e6d34e8fb494fe2b576d16037c61ba9d10722ba3 1 1 3
|
||||
author Thorsten Ball
|
||||
author-mail <mrnugget@gmail.com>
|
||||
author-time 1709299737
|
||||
author-tz +0100
|
||||
committer Thorsten Ball
|
||||
committer-mail <mrnugget@gmail.com>
|
||||
committer-time 1709299737
|
||||
committer-tz +0100
|
||||
summary Initial
|
||||
boundary
|
||||
filename file_b.txt
|
||||
e6d34e8fb494fe2b576d16037c61ba9d10722ba3 9 13 2
|
||||
filename file_b.txt
|
||||
e6d34e8fb494fe2b576d16037c61ba9d10722ba3 13 19 1
|
||||
filename file_b.txt
|
||||
@@ -0,0 +1,70 @@
|
||||
0000000000000000000000000000000000000000 3 3 1
|
||||
author Not Committed Yet
|
||||
author-mail <not.committed.yet>
|
||||
author-time 1709895274
|
||||
author-tz +0100
|
||||
committer Not Committed Yet
|
||||
committer-mail <not.committed.yet>
|
||||
committer-time 1709895274
|
||||
committer-tz +0100
|
||||
summary Version of index.js from index.js
|
||||
previous a7037b4567dd171bfe563c761354ec9236c803b3 index.js
|
||||
filename index.js
|
||||
0000000000000000000000000000000000000000 7 7 2
|
||||
previous a7037b4567dd171bfe563c761354ec9236c803b3 index.js
|
||||
filename index.js
|
||||
c8d34ae30c87e59aaa5eb65f6c64d6206f525d7c 7 6 1
|
||||
author Thorsten Ball
|
||||
author-mail <mrnugget@example.com>
|
||||
author-time 1709808710
|
||||
author-tz +0100
|
||||
committer Thorsten Ball
|
||||
committer-mail <mrnugget@example.com>
|
||||
committer-time 1709808710
|
||||
committer-tz +0100
|
||||
summary Make a commit
|
||||
previous 6ad46b5257ba16d12c5ca9f0d4900320959df7f4 index.js
|
||||
filename index.js
|
||||
6ad46b5257ba16d12c5ca9f0d4900320959df7f4 2 2 1
|
||||
author Joe Schmoe
|
||||
author-mail <joe.schmoe@example.com>
|
||||
author-time 1709741400
|
||||
author-tz +0100
|
||||
committer Joe Schmoe
|
||||
committer-mail <joe.schmoe@example.com>
|
||||
committer-time 1709741400
|
||||
committer-tz +0100
|
||||
summary Joe's cool commit
|
||||
previous 486c2409237a2c627230589e567024a96751d475 index.js
|
||||
filename index.js
|
||||
6ad46b5257ba16d12c5ca9f0d4900320959df7f4 3 4 1
|
||||
previous 486c2409237a2c627230589e567024a96751d475 index.js
|
||||
filename index.js
|
||||
6ad46b5257ba16d12c5ca9f0d4900320959df7f4 13 9 1
|
||||
previous 486c2409237a2c627230589e567024a96751d475 index.js
|
||||
filename index.js
|
||||
486c2409237a2c627230589e567024a96751d475 3 1 1
|
||||
author Thorsten Ball
|
||||
author-mail <mrnugget@example.com>
|
||||
author-time 1709129122
|
||||
author-tz +0100
|
||||
committer Thorsten Ball
|
||||
committer-mail <mrnugget@example.com>
|
||||
committer-time 1709129122
|
||||
committer-tz +0100
|
||||
summary Get to a state where eslint would change code and imports
|
||||
previous 504065e448b467e79920040f22153e9d2ea0fd6e index.js
|
||||
filename index.js
|
||||
504065e448b467e79920040f22153e9d2ea0fd6e 3 5 1
|
||||
author Thorsten Ball
|
||||
author-mail <mrnugget@example.com>
|
||||
author-time 1709128963
|
||||
author-tz +0100
|
||||
committer Thorsten Ball
|
||||
committer-mail <mrnugget@example.com>
|
||||
committer-time 1709128963
|
||||
committer-tz +0100
|
||||
summary Add some stuff
|
||||
filename index.js
|
||||
504065e448b467e79920040f22153e9d2ea0fd6e 21 10 1
|
||||
filename index.js
|
||||
@@ -0,0 +1,781 @@
|
||||
[
|
||||
{
|
||||
"sha": "5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206",
|
||||
"range": {
|
||||
"start": 5,
|
||||
"end": 8
|
||||
},
|
||||
"original_line_number": 6,
|
||||
"author": "Mahdy M. Karam",
|
||||
"author_mail": "<64036912+mmkaram@users.noreply.github.com>",
|
||||
"author_time": 1708621949,
|
||||
"author_tz": "-0800",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1708621949,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Add option to either use system clipboard or vim clipboard (#7936)",
|
||||
"previous": "c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206",
|
||||
"range": {
|
||||
"start": 11,
|
||||
"end": 13
|
||||
},
|
||||
"original_line_number": 12,
|
||||
"author": "Mahdy M. Karam",
|
||||
"author_mail": "<64036912+mmkaram@users.noreply.github.com>",
|
||||
"author_time": 1708621949,
|
||||
"author_tz": "-0800",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1708621949,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Add option to either use system clipboard or vim clipboard (#7936)",
|
||||
"previous": "c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206",
|
||||
"range": {
|
||||
"start": 17,
|
||||
"end": 18
|
||||
},
|
||||
"original_line_number": 18,
|
||||
"author": "Mahdy M. Karam",
|
||||
"author_mail": "<64036912+mmkaram@users.noreply.github.com>",
|
||||
"author_time": 1708621949,
|
||||
"author_tz": "-0800",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1708621949,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Add option to either use system clipboard or vim clipboard (#7936)",
|
||||
"previous": "c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206",
|
||||
"range": {
|
||||
"start": 20,
|
||||
"end": 27
|
||||
},
|
||||
"original_line_number": 21,
|
||||
"author": "Mahdy M. Karam",
|
||||
"author_mail": "<64036912+mmkaram@users.noreply.github.com>",
|
||||
"author_time": 1708621949,
|
||||
"author_tz": "-0800",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1708621949,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Add option to either use system clipboard or vim clipboard (#7936)",
|
||||
"previous": "c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206",
|
||||
"range": {
|
||||
"start": 30,
|
||||
"end": 31
|
||||
},
|
||||
"original_line_number": 31,
|
||||
"author": "Mahdy M. Karam",
|
||||
"author_mail": "<64036912+mmkaram@users.noreply.github.com>",
|
||||
"author_time": 1708621949,
|
||||
"author_tz": "-0800",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1708621949,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Add option to either use system clipboard or vim clipboard (#7936)",
|
||||
"previous": "c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206",
|
||||
"range": {
|
||||
"start": 33,
|
||||
"end": 34
|
||||
},
|
||||
"original_line_number": 34,
|
||||
"author": "Mahdy M. Karam",
|
||||
"author_mail": "<64036912+mmkaram@users.noreply.github.com>",
|
||||
"author_time": 1708621949,
|
||||
"author_tz": "-0800",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1708621949,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Add option to either use system clipboard or vim clipboard (#7936)",
|
||||
"previous": "c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "5c4f3c0ceaa0b2270c8f4fc8ee32b85c70810206",
|
||||
"range": {
|
||||
"start": 85,
|
||||
"end": 101
|
||||
},
|
||||
"original_line_number": 86,
|
||||
"author": "Mahdy M. Karam",
|
||||
"author_mail": "<64036912+mmkaram@users.noreply.github.com>",
|
||||
"author_time": 1708621949,
|
||||
"author_tz": "-0800",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1708621949,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Add option to either use system clipboard or vim clipboard (#7936)",
|
||||
"previous": "c6826a61a0a947acf09d65ada568c9c4e4494cb2 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "3635d2dcedd83f1b6702f33ca2673317f7fa4695",
|
||||
"range": {
|
||||
"start": 0,
|
||||
"end": 2
|
||||
},
|
||||
"original_line_number": 1,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1707520689,
|
||||
"author_tz": "-0700",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1707520689,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Highlight selections on vim yank (#7638)",
|
||||
"previous": "efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "3635d2dcedd83f1b6702f33ca2673317f7fa4695",
|
||||
"range": {
|
||||
"start": 3,
|
||||
"end": 4
|
||||
},
|
||||
"original_line_number": 4,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1707520689,
|
||||
"author_tz": "-0700",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1707520689,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Highlight selections on vim yank (#7638)",
|
||||
"previous": "efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "3635d2dcedd83f1b6702f33ca2673317f7fa4695",
|
||||
"range": {
|
||||
"start": 9,
|
||||
"end": 11
|
||||
},
|
||||
"original_line_number": 7,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1707520689,
|
||||
"author_tz": "-0700",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1707520689,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Highlight selections on vim yank (#7638)",
|
||||
"previous": "efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "3635d2dcedd83f1b6702f33ca2673317f7fa4695",
|
||||
"range": {
|
||||
"start": 13,
|
||||
"end": 17
|
||||
},
|
||||
"original_line_number": 10,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1707520689,
|
||||
"author_tz": "-0700",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1707520689,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Highlight selections on vim yank (#7638)",
|
||||
"previous": "efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "3635d2dcedd83f1b6702f33ca2673317f7fa4695",
|
||||
"range": {
|
||||
"start": 18,
|
||||
"end": 20
|
||||
},
|
||||
"original_line_number": 15,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1707520689,
|
||||
"author_tz": "-0700",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1707520689,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Highlight selections on vim yank (#7638)",
|
||||
"previous": "efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "3635d2dcedd83f1b6702f33ca2673317f7fa4695",
|
||||
"range": {
|
||||
"start": 27,
|
||||
"end": 30
|
||||
},
|
||||
"original_line_number": 19,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1707520689,
|
||||
"author_tz": "-0700",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1707520689,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Highlight selections on vim yank (#7638)",
|
||||
"previous": "efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "3635d2dcedd83f1b6702f33ca2673317f7fa4695",
|
||||
"range": {
|
||||
"start": 31,
|
||||
"end": 33
|
||||
},
|
||||
"original_line_number": 22,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1707520689,
|
||||
"author_tz": "-0700",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1707520689,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Highlight selections on vim yank (#7638)",
|
||||
"previous": "efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "3635d2dcedd83f1b6702f33ca2673317f7fa4695",
|
||||
"range": {
|
||||
"start": 34,
|
||||
"end": 36
|
||||
},
|
||||
"original_line_number": 25,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1707520689,
|
||||
"author_tz": "-0700",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1707520689,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Highlight selections on vim yank (#7638)",
|
||||
"previous": "efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "3635d2dcedd83f1b6702f33ca2673317f7fa4695",
|
||||
"range": {
|
||||
"start": 40,
|
||||
"end": 41
|
||||
},
|
||||
"original_line_number": 31,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1707520689,
|
||||
"author_tz": "-0700",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1707520689,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Highlight selections on vim yank (#7638)",
|
||||
"previous": "efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "3635d2dcedd83f1b6702f33ca2673317f7fa4695",
|
||||
"range": {
|
||||
"start": 66,
|
||||
"end": 71
|
||||
},
|
||||
"original_line_number": 57,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1707520689,
|
||||
"author_tz": "-0700",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1707520689,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Highlight selections on vim yank (#7638)",
|
||||
"previous": "efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "3635d2dcedd83f1b6702f33ca2673317f7fa4695",
|
||||
"range": {
|
||||
"start": 101,
|
||||
"end": 119
|
||||
},
|
||||
"original_line_number": 78,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1707520689,
|
||||
"author_tz": "-0700",
|
||||
"committer": "GitHub",
|
||||
"committer_mail": "<noreply@github.com>",
|
||||
"committer_time": 1707520689,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Highlight selections on vim yank (#7638)",
|
||||
"previous": "efe23ebfcdd653b13be79132b1e2925bcd7bde45 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "b65cf6d2d9576171edb407f5bbaa231c33af1f71",
|
||||
"range": {
|
||||
"start": 4,
|
||||
"end": 5
|
||||
},
|
||||
"original_line_number": 3,
|
||||
"author": "Max Brunsfeld",
|
||||
"author_mail": "<maxbrunsfeld@gmail.com>",
|
||||
"author_time": 1705619094,
|
||||
"author_tz": "-0800",
|
||||
"committer": "Max Brunsfeld",
|
||||
"committer_mail": "<maxbrunsfeld@gmail.com>",
|
||||
"committer_time": 1705619205,
|
||||
"committer_tz": "-0800",
|
||||
"summary": "Merge branch 'main' into language-api-docs",
|
||||
"previous": "6457ccf9ece3b36a37e675783abee9748a443115 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "b65cf6d2d9576171edb407f5bbaa231c33af1f71",
|
||||
"range": {
|
||||
"start": 120,
|
||||
"end": 128
|
||||
},
|
||||
"original_line_number": 51,
|
||||
"author": "Max Brunsfeld",
|
||||
"author_mail": "<maxbrunsfeld@gmail.com>",
|
||||
"author_time": 1705619094,
|
||||
"author_tz": "-0800",
|
||||
"committer": "Max Brunsfeld",
|
||||
"committer_mail": "<maxbrunsfeld@gmail.com>",
|
||||
"committer_time": 1705619205,
|
||||
"committer_tz": "-0800",
|
||||
"summary": "Merge branch 'main' into language-api-docs",
|
||||
"previous": "6457ccf9ece3b36a37e675783abee9748a443115 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "b02bd9bce1db3a68dcd606718fa02709020860af",
|
||||
"range": {
|
||||
"start": 60,
|
||||
"end": 61
|
||||
},
|
||||
"original_line_number": 29,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1694798044,
|
||||
"author_tz": "-0600",
|
||||
"committer": "Conrad Irwin",
|
||||
"committer_mail": "<conrad@zed.dev>",
|
||||
"committer_time": 1694798044,
|
||||
"committer_tz": "-0600",
|
||||
"summary": "Fix Y on last line with no trailing new line",
|
||||
"previous": "7c77baa7c17eea106330622e70513ea9389d50a1 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "b02bd9bce1db3a68dcd606718fa02709020860af",
|
||||
"range": {
|
||||
"start": 64,
|
||||
"end": 65
|
||||
},
|
||||
"original_line_number": 33,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1694798044,
|
||||
"author_tz": "-0600",
|
||||
"committer": "Conrad Irwin",
|
||||
"committer_mail": "<conrad@zed.dev>",
|
||||
"committer_time": 1694798044,
|
||||
"committer_tz": "-0600",
|
||||
"summary": "Fix Y on last line with no trailing new line",
|
||||
"previous": "7c77baa7c17eea106330622e70513ea9389d50a1 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "e4794e3134b6449e36ed2771a8849046489cc252",
|
||||
"range": {
|
||||
"start": 44,
|
||||
"end": 45
|
||||
},
|
||||
"original_line_number": 13,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1692855942,
|
||||
"author_tz": "-0600",
|
||||
"committer": "Conrad Irwin",
|
||||
"committer_mail": "<conrad@zed.dev>",
|
||||
"committer_time": 1692856812,
|
||||
"committer_tz": "-0600",
|
||||
"summary": "vim: Fix linewise copy of last line with no trailing newline",
|
||||
"previous": "26c3312049a9c73bc3350528c1defd3820a7a8c7 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "e4794e3134b6449e36ed2771a8849046489cc252",
|
||||
"range": {
|
||||
"start": 52,
|
||||
"end": 60
|
||||
},
|
||||
"original_line_number": 21,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1692855942,
|
||||
"author_tz": "-0600",
|
||||
"committer": "Conrad Irwin",
|
||||
"committer_mail": "<conrad@zed.dev>",
|
||||
"committer_time": 1692856812,
|
||||
"committer_tz": "-0600",
|
||||
"summary": "vim: Fix linewise copy of last line with no trailing newline",
|
||||
"previous": "26c3312049a9c73bc3350528c1defd3820a7a8c7 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "e4794e3134b6449e36ed2771a8849046489cc252",
|
||||
"range": {
|
||||
"start": 61,
|
||||
"end": 64
|
||||
},
|
||||
"original_line_number": 29,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1692855942,
|
||||
"author_tz": "-0600",
|
||||
"committer": "Conrad Irwin",
|
||||
"committer_mail": "<conrad@zed.dev>",
|
||||
"committer_time": 1692856812,
|
||||
"committer_tz": "-0600",
|
||||
"summary": "vim: Fix linewise copy of last line with no trailing newline",
|
||||
"previous": "26c3312049a9c73bc3350528c1defd3820a7a8c7 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "e4794e3134b6449e36ed2771a8849046489cc252",
|
||||
"range": {
|
||||
"start": 65,
|
||||
"end": 66
|
||||
},
|
||||
"original_line_number": 33,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1692855942,
|
||||
"author_tz": "-0600",
|
||||
"committer": "Conrad Irwin",
|
||||
"committer_mail": "<conrad@zed.dev>",
|
||||
"committer_time": 1692856812,
|
||||
"committer_tz": "-0600",
|
||||
"summary": "vim: Fix linewise copy of last line with no trailing newline",
|
||||
"previous": "26c3312049a9c73bc3350528c1defd3820a7a8c7 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "e4794e3134b6449e36ed2771a8849046489cc252",
|
||||
"range": {
|
||||
"start": 74,
|
||||
"end": 77
|
||||
},
|
||||
"original_line_number": 37,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1692855942,
|
||||
"author_tz": "-0600",
|
||||
"committer": "Conrad Irwin",
|
||||
"committer_mail": "<conrad@zed.dev>",
|
||||
"committer_time": 1692856812,
|
||||
"committer_tz": "-0600",
|
||||
"summary": "vim: Fix linewise copy of last line with no trailing newline",
|
||||
"previous": "26c3312049a9c73bc3350528c1defd3820a7a8c7 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "33d7fe02ee560f6ed57d1425c43e60aef3b66e64",
|
||||
"range": {
|
||||
"start": 42,
|
||||
"end": 43
|
||||
},
|
||||
"original_line_number": 10,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1692644159,
|
||||
"author_tz": "-0600",
|
||||
"committer": "Conrad Irwin",
|
||||
"committer_mail": "<conrad@zed.dev>",
|
||||
"committer_time": 1692732477,
|
||||
"committer_tz": "-0600",
|
||||
"summary": "Rewrite paste",
|
||||
"previous": "31db5e4f62e8fca75aa0870f903ae044524c3580 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "33d7fe02ee560f6ed57d1425c43e60aef3b66e64",
|
||||
"range": {
|
||||
"start": 46,
|
||||
"end": 52
|
||||
},
|
||||
"original_line_number": 14,
|
||||
"author": "Conrad Irwin",
|
||||
"author_mail": "<conrad@zed.dev>",
|
||||
"author_time": 1692644159,
|
||||
"author_tz": "-0600",
|
||||
"committer": "Conrad Irwin",
|
||||
"committer_mail": "<conrad@zed.dev>",
|
||||
"committer_time": 1692732477,
|
||||
"committer_tz": "-0600",
|
||||
"summary": "Rewrite paste",
|
||||
"previous": "31db5e4f62e8fca75aa0870f903ae044524c3580 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "868c46062008bb0bcab2d41a38b4295996b9b958",
|
||||
"range": {
|
||||
"start": 80,
|
||||
"end": 81
|
||||
},
|
||||
"original_line_number": 20,
|
||||
"author": "Max Brunsfeld",
|
||||
"author_mail": "<maxbrunsfeld@gmail.com>",
|
||||
"author_time": 1659072896,
|
||||
"author_tz": "-0700",
|
||||
"committer": "Max Brunsfeld",
|
||||
"committer_mail": "<maxbrunsfeld@gmail.com>",
|
||||
"committer_time": 1659073230,
|
||||
"committer_tz": "-0700",
|
||||
"summary": ":art: Rename and simplify some autoindent stuff",
|
||||
"previous": "7a26fa18c7fee3fe031b991e18b55fd8f9c4eb1b crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "e93c49f4f02b3edaddae6a6a4cc0ac433f242357",
|
||||
"range": {
|
||||
"start": 36,
|
||||
"end": 37
|
||||
},
|
||||
"original_line_number": 5,
|
||||
"author": "Kaylee Simmons",
|
||||
"author_mail": "<kay@the-simmons.net>",
|
||||
"author_time": 1653424557,
|
||||
"author_tz": "-0700",
|
||||
"committer": "Kaylee Simmons",
|
||||
"committer_mail": "<kay@the-simmons.net>",
|
||||
"committer_time": 1653609725,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Unify visual line_mode and non line_mode operators",
|
||||
"previous": "11569a869a72f786a9798c53266e28c05c79f824 crates/vim/src/utils.rs",
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "082036161fd3815c831ceedfd28ba15b0ed6eb9f",
|
||||
"range": {
|
||||
"start": 2,
|
||||
"end": 3
|
||||
},
|
||||
"original_line_number": 1,
|
||||
"author": "Kaylee Simmons",
|
||||
"author_mail": "<kay@the-simmons.net>",
|
||||
"author_time": 1653007350,
|
||||
"author_tz": "-0700",
|
||||
"committer": "Kaylee Simmons",
|
||||
"committer_mail": "<kay@the-simmons.net>",
|
||||
"committer_time": 1653609725,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Enable copy and paste in vim mode",
|
||||
"previous": null,
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "082036161fd3815c831ceedfd28ba15b0ed6eb9f",
|
||||
"range": {
|
||||
"start": 8,
|
||||
"end": 9
|
||||
},
|
||||
"original_line_number": 4,
|
||||
"author": "Kaylee Simmons",
|
||||
"author_mail": "<kay@the-simmons.net>",
|
||||
"author_time": 1653007350,
|
||||
"author_tz": "-0700",
|
||||
"committer": "Kaylee Simmons",
|
||||
"committer_mail": "<kay@the-simmons.net>",
|
||||
"committer_time": 1653609725,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Enable copy and paste in vim mode",
|
||||
"previous": null,
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "082036161fd3815c831ceedfd28ba15b0ed6eb9f",
|
||||
"range": {
|
||||
"start": 37,
|
||||
"end": 40
|
||||
},
|
||||
"original_line_number": 7,
|
||||
"author": "Kaylee Simmons",
|
||||
"author_mail": "<kay@the-simmons.net>",
|
||||
"author_time": 1653007350,
|
||||
"author_tz": "-0700",
|
||||
"committer": "Kaylee Simmons",
|
||||
"committer_mail": "<kay@the-simmons.net>",
|
||||
"committer_time": 1653609725,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Enable copy and paste in vim mode",
|
||||
"previous": null,
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "082036161fd3815c831ceedfd28ba15b0ed6eb9f",
|
||||
"range": {
|
||||
"start": 41,
|
||||
"end": 42
|
||||
},
|
||||
"original_line_number": 10,
|
||||
"author": "Kaylee Simmons",
|
||||
"author_mail": "<kay@the-simmons.net>",
|
||||
"author_time": 1653007350,
|
||||
"author_tz": "-0700",
|
||||
"committer": "Kaylee Simmons",
|
||||
"committer_mail": "<kay@the-simmons.net>",
|
||||
"committer_time": 1653609725,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Enable copy and paste in vim mode",
|
||||
"previous": null,
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "082036161fd3815c831ceedfd28ba15b0ed6eb9f",
|
||||
"range": {
|
||||
"start": 43,
|
||||
"end": 44
|
||||
},
|
||||
"original_line_number": 11,
|
||||
"author": "Kaylee Simmons",
|
||||
"author_mail": "<kay@the-simmons.net>",
|
||||
"author_time": 1653007350,
|
||||
"author_tz": "-0700",
|
||||
"committer": "Kaylee Simmons",
|
||||
"committer_mail": "<kay@the-simmons.net>",
|
||||
"committer_time": 1653609725,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Enable copy and paste in vim mode",
|
||||
"previous": null,
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "082036161fd3815c831ceedfd28ba15b0ed6eb9f",
|
||||
"range": {
|
||||
"start": 45,
|
||||
"end": 46
|
||||
},
|
||||
"original_line_number": 14,
|
||||
"author": "Kaylee Simmons",
|
||||
"author_mail": "<kay@the-simmons.net>",
|
||||
"author_time": 1653007350,
|
||||
"author_tz": "-0700",
|
||||
"committer": "Kaylee Simmons",
|
||||
"committer_mail": "<kay@the-simmons.net>",
|
||||
"committer_time": 1653609725,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Enable copy and paste in vim mode",
|
||||
"previous": null,
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "082036161fd3815c831ceedfd28ba15b0ed6eb9f",
|
||||
"range": {
|
||||
"start": 71,
|
||||
"end": 74
|
||||
},
|
||||
"original_line_number": 15,
|
||||
"author": "Kaylee Simmons",
|
||||
"author_mail": "<kay@the-simmons.net>",
|
||||
"author_time": 1653007350,
|
||||
"author_tz": "-0700",
|
||||
"committer": "Kaylee Simmons",
|
||||
"committer_mail": "<kay@the-simmons.net>",
|
||||
"committer_time": 1653609725,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Enable copy and paste in vim mode",
|
||||
"previous": null,
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "082036161fd3815c831ceedfd28ba15b0ed6eb9f",
|
||||
"range": {
|
||||
"start": 77,
|
||||
"end": 80
|
||||
},
|
||||
"original_line_number": 18,
|
||||
"author": "Kaylee Simmons",
|
||||
"author_mail": "<kay@the-simmons.net>",
|
||||
"author_time": 1653007350,
|
||||
"author_tz": "-0700",
|
||||
"committer": "Kaylee Simmons",
|
||||
"committer_mail": "<kay@the-simmons.net>",
|
||||
"committer_time": 1653609725,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Enable copy and paste in vim mode",
|
||||
"previous": null,
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "082036161fd3815c831ceedfd28ba15b0ed6eb9f",
|
||||
"range": {
|
||||
"start": 81,
|
||||
"end": 85
|
||||
},
|
||||
"original_line_number": 21,
|
||||
"author": "Kaylee Simmons",
|
||||
"author_mail": "<kay@the-simmons.net>",
|
||||
"author_time": 1653007350,
|
||||
"author_tz": "-0700",
|
||||
"committer": "Kaylee Simmons",
|
||||
"committer_mail": "<kay@the-simmons.net>",
|
||||
"committer_time": 1653609725,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Enable copy and paste in vim mode",
|
||||
"previous": null,
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
},
|
||||
{
|
||||
"sha": "082036161fd3815c831ceedfd28ba15b0ed6eb9f",
|
||||
"range": {
|
||||
"start": 119,
|
||||
"end": 120
|
||||
},
|
||||
"original_line_number": 26,
|
||||
"author": "Kaylee Simmons",
|
||||
"author_mail": "<kay@the-simmons.net>",
|
||||
"author_time": 1653007350,
|
||||
"author_tz": "-0700",
|
||||
"committer": "Kaylee Simmons",
|
||||
"committer_mail": "<kay@the-simmons.net>",
|
||||
"committer_time": 1653609725,
|
||||
"committer_tz": "-0700",
|
||||
"summary": "Enable copy and paste in vim mode",
|
||||
"previous": null,
|
||||
"filename": "crates/vim/src/utils.rs"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,135 @@
|
||||
[
|
||||
{
|
||||
"sha": "4aaba34cb86b12f3a749dd6ddbf185de88de6527",
|
||||
"range": {
|
||||
"start": 6,
|
||||
"end": 8
|
||||
},
|
||||
"original_line_number": 4,
|
||||
"author": "Thorsten Ball",
|
||||
"author_mail": "<mrnugget@gmail.com>",
|
||||
"author_time": 1710764113,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Thorsten Ball",
|
||||
"committer_mail": "<mrnugget@gmail.com>",
|
||||
"committer_time": 1710764113,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Another commit",
|
||||
"previous": "b2f6b0d982a9e7654bbb6d979c9ccb00b1d2e913 file_b.txt",
|
||||
"filename": "file_b.txt"
|
||||
},
|
||||
{
|
||||
"sha": "4aaba34cb86b12f3a749dd6ddbf185de88de6527",
|
||||
"range": {
|
||||
"start": 16,
|
||||
"end": 18
|
||||
},
|
||||
"original_line_number": 11,
|
||||
"author": "Thorsten Ball",
|
||||
"author_mail": "<mrnugget@gmail.com>",
|
||||
"author_time": 1710764113,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Thorsten Ball",
|
||||
"committer_mail": "<mrnugget@gmail.com>",
|
||||
"committer_time": 1710764113,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Another commit",
|
||||
"previous": "b2f6b0d982a9e7654bbb6d979c9ccb00b1d2e913 file_b.txt",
|
||||
"filename": "file_b.txt"
|
||||
},
|
||||
{
|
||||
"sha": "b2f6b0d982a9e7654bbb6d979c9ccb00b1d2e913",
|
||||
"range": {
|
||||
"start": 8,
|
||||
"end": 9
|
||||
},
|
||||
"original_line_number": 6,
|
||||
"author": "Thorsten Ball",
|
||||
"author_mail": "<mrnugget@gmail.com>",
|
||||
"author_time": 1710764087,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Thorsten Ball",
|
||||
"committer_mail": "<mrnugget@gmail.com>",
|
||||
"committer_time": 1710764087,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Another commit",
|
||||
"previous": "7aef8a9a211ebc86824769c89f48e4f64aa6183f file_b.txt",
|
||||
"filename": "file_b.txt"
|
||||
},
|
||||
{
|
||||
"sha": "b2f6b0d982a9e7654bbb6d979c9ccb00b1d2e913",
|
||||
"range": {
|
||||
"start": 10,
|
||||
"end": 12
|
||||
},
|
||||
"original_line_number": 7,
|
||||
"author": "Thorsten Ball",
|
||||
"author_mail": "<mrnugget@gmail.com>",
|
||||
"author_time": 1710764087,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Thorsten Ball",
|
||||
"committer_mail": "<mrnugget@gmail.com>",
|
||||
"committer_time": 1710764087,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Another commit",
|
||||
"previous": "7aef8a9a211ebc86824769c89f48e4f64aa6183f file_b.txt",
|
||||
"filename": "file_b.txt"
|
||||
},
|
||||
{
|
||||
"sha": "e6d34e8fb494fe2b576d16037c61ba9d10722ba3",
|
||||
"range": {
|
||||
"start": 0,
|
||||
"end": 3
|
||||
},
|
||||
"original_line_number": 1,
|
||||
"author": "Thorsten Ball",
|
||||
"author_mail": "<mrnugget@gmail.com>",
|
||||
"author_time": 1709299737,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Thorsten Ball",
|
||||
"committer_mail": "<mrnugget@gmail.com>",
|
||||
"committer_time": 1709299737,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Initial",
|
||||
"previous": null,
|
||||
"filename": "file_b.txt"
|
||||
},
|
||||
{
|
||||
"sha": "e6d34e8fb494fe2b576d16037c61ba9d10722ba3",
|
||||
"range": {
|
||||
"start": 12,
|
||||
"end": 14
|
||||
},
|
||||
"original_line_number": 9,
|
||||
"author": "Thorsten Ball",
|
||||
"author_mail": "<mrnugget@gmail.com>",
|
||||
"author_time": 1709299737,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Thorsten Ball",
|
||||
"committer_mail": "<mrnugget@gmail.com>",
|
||||
"committer_time": 1709299737,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Initial",
|
||||
"previous": null,
|
||||
"filename": "file_b.txt"
|
||||
},
|
||||
{
|
||||
"sha": "e6d34e8fb494fe2b576d16037c61ba9d10722ba3",
|
||||
"range": {
|
||||
"start": 18,
|
||||
"end": 19
|
||||
},
|
||||
"original_line_number": 13,
|
||||
"author": "Thorsten Ball",
|
||||
"author_mail": "<mrnugget@gmail.com>",
|
||||
"author_time": 1709299737,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Thorsten Ball",
|
||||
"committer_mail": "<mrnugget@gmail.com>",
|
||||
"committer_time": 1709299737,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Initial",
|
||||
"previous": null,
|
||||
"filename": "file_b.txt"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,135 @@
|
||||
[
|
||||
{
|
||||
"sha": "c8d34ae30c87e59aaa5eb65f6c64d6206f525d7c",
|
||||
"range": {
|
||||
"start": 5,
|
||||
"end": 6
|
||||
},
|
||||
"original_line_number": 7,
|
||||
"author": "Thorsten Ball",
|
||||
"author_mail": "<mrnugget@example.com>",
|
||||
"author_time": 1709808710,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Thorsten Ball",
|
||||
"committer_mail": "<mrnugget@example.com>",
|
||||
"committer_time": 1709808710,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Make a commit",
|
||||
"previous": "6ad46b5257ba16d12c5ca9f0d4900320959df7f4 index.js",
|
||||
"filename": "index.js"
|
||||
},
|
||||
{
|
||||
"sha": "6ad46b5257ba16d12c5ca9f0d4900320959df7f4",
|
||||
"range": {
|
||||
"start": 1,
|
||||
"end": 2
|
||||
},
|
||||
"original_line_number": 2,
|
||||
"author": "Joe Schmoe",
|
||||
"author_mail": "<joe.schmoe@example.com>",
|
||||
"author_time": 1709741400,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Joe Schmoe",
|
||||
"committer_mail": "<joe.schmoe@example.com>",
|
||||
"committer_time": 1709741400,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Joe's cool commit",
|
||||
"previous": "486c2409237a2c627230589e567024a96751d475 index.js",
|
||||
"filename": "index.js"
|
||||
},
|
||||
{
|
||||
"sha": "6ad46b5257ba16d12c5ca9f0d4900320959df7f4",
|
||||
"range": {
|
||||
"start": 3,
|
||||
"end": 4
|
||||
},
|
||||
"original_line_number": 3,
|
||||
"author": "Joe Schmoe",
|
||||
"author_mail": "<joe.schmoe@example.com>",
|
||||
"author_time": 1709741400,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Joe Schmoe",
|
||||
"committer_mail": "<joe.schmoe@example.com>",
|
||||
"committer_time": 1709741400,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Joe's cool commit",
|
||||
"previous": "486c2409237a2c627230589e567024a96751d475 index.js",
|
||||
"filename": "index.js"
|
||||
},
|
||||
{
|
||||
"sha": "6ad46b5257ba16d12c5ca9f0d4900320959df7f4",
|
||||
"range": {
|
||||
"start": 8,
|
||||
"end": 9
|
||||
},
|
||||
"original_line_number": 13,
|
||||
"author": "Joe Schmoe",
|
||||
"author_mail": "<joe.schmoe@example.com>",
|
||||
"author_time": 1709741400,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Joe Schmoe",
|
||||
"committer_mail": "<joe.schmoe@example.com>",
|
||||
"committer_time": 1709741400,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Joe's cool commit",
|
||||
"previous": "486c2409237a2c627230589e567024a96751d475 index.js",
|
||||
"filename": "index.js"
|
||||
},
|
||||
{
|
||||
"sha": "486c2409237a2c627230589e567024a96751d475",
|
||||
"range": {
|
||||
"start": 0,
|
||||
"end": 1
|
||||
},
|
||||
"original_line_number": 3,
|
||||
"author": "Thorsten Ball",
|
||||
"author_mail": "<mrnugget@example.com>",
|
||||
"author_time": 1709129122,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Thorsten Ball",
|
||||
"committer_mail": "<mrnugget@example.com>",
|
||||
"committer_time": 1709129122,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Get to a state where eslint would change code and imports",
|
||||
"previous": "504065e448b467e79920040f22153e9d2ea0fd6e index.js",
|
||||
"filename": "index.js"
|
||||
},
|
||||
{
|
||||
"sha": "504065e448b467e79920040f22153e9d2ea0fd6e",
|
||||
"range": {
|
||||
"start": 4,
|
||||
"end": 5
|
||||
},
|
||||
"original_line_number": 3,
|
||||
"author": "Thorsten Ball",
|
||||
"author_mail": "<mrnugget@example.com>",
|
||||
"author_time": 1709128963,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Thorsten Ball",
|
||||
"committer_mail": "<mrnugget@example.com>",
|
||||
"committer_time": 1709128963,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Add some stuff",
|
||||
"previous": null,
|
||||
"filename": "index.js"
|
||||
},
|
||||
{
|
||||
"sha": "504065e448b467e79920040f22153e9d2ea0fd6e",
|
||||
"range": {
|
||||
"start": 9,
|
||||
"end": 10
|
||||
},
|
||||
"original_line_number": 21,
|
||||
"author": "Thorsten Ball",
|
||||
"author_mail": "<mrnugget@example.com>",
|
||||
"author_time": 1709128963,
|
||||
"author_tz": "+0100",
|
||||
"committer": "Thorsten Ball",
|
||||
"committer_mail": "<mrnugget@example.com>",
|
||||
"committer_time": 1709128963,
|
||||
"committer_tz": "+0100",
|
||||
"summary": "Add some stuff",
|
||||
"previous": null,
|
||||
"filename": "index.js"
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user