1class Gitg.DiffViewFileInfo : Object 2{ 3 public Ggit.DiffDelta delta { get; construct set; } 4 public bool from_workdir { get; construct set; } 5 public Repository? repository { get; construct set; } 6 7 public InputStream? new_file_input_stream { get; set; } 8 public string? new_file_content_type { get; private set; } 9 10 public DiffViewFileInfo(Repository? repository, Ggit.DiffDelta delta, bool from_workdir) 11 { 12 Object(repository: repository, delta: delta, from_workdir: from_workdir); 13 } 14 15 public async void query(Cancellable? cancellable) 16 { 17 yield query_content(cancellable); 18 } 19 20 private async void query_content(Cancellable? cancellable) 21 { 22 var file = delta.get_new_file(); 23 var id = file.get_oid(); 24 var path = file.get_path(); 25 26 if (repository == null || (id.is_zero() && !from_workdir) || (path == null && from_workdir)) 27 { 28 return; 29 } 30 31 var workdir = repository.get_workdir(); 32 File location = workdir != null ? workdir.get_child(path) : null; 33 34 if (!from_workdir) 35 { 36 Ggit.Blob blob; 37 38 try 39 { 40 blob = repository.lookup<Ggit.Blob>(id); 41 } 42 catch (Error e) 43 { 44 return; 45 } 46 47 var bytes = new Bytes(blob.get_raw_content()); 48 new_file_input_stream = new GLib.MemoryInputStream.from_bytes(bytes); 49 } 50 else if (location != null) 51 { 52 // Try to read from disk 53 try 54 { 55 new_file_input_stream = yield location.read_async(Priority.DEFAULT, cancellable); 56 } 57 catch 58 { 59 return; 60 } 61 } 62 63 var seekable = new_file_input_stream as Seekable; 64 65 if (seekable != null && seekable.can_seek()) 66 { 67 // Read a little bit of content to guess the type 68 yield guess_content_type(new_file_input_stream, location != null ? location.get_basename() : null, cancellable); 69 70 try 71 { 72 seekable.seek(0, SeekType.SET, cancellable); 73 } 74 catch (Error e) 75 { 76 stderr.printf("Failed to seek back to beginning of stream...\n"); 77 new_file_input_stream = null; 78 } 79 } 80 } 81 82 private async void guess_content_type(InputStream stream, string basename, Cancellable? cancellable) 83 { 84 var buffer = new uint8[4096]; 85 size_t bytes_read = 0; 86 87 try 88 { 89 yield stream.read_all_async(buffer, Priority.DEFAULT, cancellable, out bytes_read); 90 } 91 catch (Error e) 92 { 93 if (bytes_read <= 0) 94 { 95 return; 96 } 97 } 98 99 buffer.length = (int)bytes_read; 100 101 bool uncertain; 102 new_file_content_type = GLib.ContentType.guess(basename, buffer, out uncertain); 103 104 } 105}