File: gitg-diff-view-file-info.vala

package info (click to toggle)
gitg 41-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 18,876 kB
  • sloc: ansic: 1,636; ruby: 1,445; sh: 314; python: 261; xml: 57; makefile: 15
file content (119 lines) | stat: -rw-r--r-- 2,974 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
class Gitg.DiffViewFileInfo : Object
{
	public Ggit.DiffDelta delta { get; construct set; }
	public bool from_workdir { get; construct set; }
	public Repository? repository { get; construct set; }

	public InputStream? new_file_input_stream { get; set; }
	public string? new_file_content_type { get; private set; }

	public DiffViewFileInfo(Repository? repository, Ggit.DiffDelta delta, bool from_workdir)
	{
		Object(repository: repository, delta: delta, from_workdir: from_workdir);
	}

	public async void query(Cancellable? cancellable)
	{
		yield query_content(cancellable);
	}

	private async void query_content(Cancellable? cancellable)
	{
		var file = delta.get_new_file();
		var id = file.get_oid();
		var path = file.get_path();

		if (repository == null || (id.is_zero() && !from_workdir) || (path == null && from_workdir))
		{
			return;
		}

		var workdir = repository.get_workdir();
		File location = workdir != null ? workdir.get_child(path) : null;

		if (!from_workdir)
		{
			Ggit.Blob blob;

			try
			{
				blob = repository.lookup<Ggit.Blob>(id);
			}
			catch (Error e)
			{
				return;
			}

			uint8[]? raw_content = blob.get_raw_content();
			if (TextConv.has_textconv_command(repository, file))
				raw_content = TextConv.get_textconv_content_from_raw(repository, file, raw_content);
			var bytes = new Bytes(raw_content);
			new_file_input_stream = new GLib.MemoryInputStream.from_bytes(bytes);
		}
		else if (location != null)
		{
			// Try to read from disk
			try
			{
				if (TextConv.has_textconv_command(repository, file))
				{
					uint8[]? content = null;
					yield location.load_contents_async(cancellable, out content, null);
					content = TextConv.get_textconv_content_from_raw(repository, file, content);
					var bytes = new Bytes(content);
					new_file_input_stream = new GLib.MemoryInputStream.from_bytes(bytes);
				}
				else
				{
					new_file_input_stream = yield location.read_async(Priority.DEFAULT, cancellable);
				}
			}
			catch
			{
				return;
			}
		}

		var seekable = new_file_input_stream as Seekable;

		if (seekable != null && seekable.can_seek())
		{
			// Read a little bit of content to guess the type
			yield guess_content_type(new_file_input_stream, location != null ? location.get_basename() : null, cancellable);

			try
			{
				seekable.seek(0, SeekType.SET, cancellable);
			}
			catch (Error e)
			{
				stderr.printf("Failed to seek back to beginning of stream...\n");
				new_file_input_stream = null;
			}
		}
	}

	private async void guess_content_type(InputStream stream, string basename, Cancellable? cancellable)
	{
		var buffer = new uint8[4096];
		size_t bytes_read = 0;

		try
		{
			yield stream.read_all_async(buffer, Priority.DEFAULT, cancellable, out bytes_read);
		}
		catch (Error e)
		{
			if (bytes_read <= 0)
			{
				return;
			}
		}

		buffer.length = (int)bytes_read;

		bool uncertain;
		new_file_content_type = GLib.ContentType.guess(basename, buffer, out uncertain);

	}
}