-
-
Notifications
You must be signed in to change notification settings - Fork 292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore(deps): update rust crate winit to 0.30 #1235
Open
renovate
wants to merge
1
commit into
dev
Choose a base branch
from
renovate/winit-0.x
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
renovate
bot
force-pushed
the
renovate/winit-0.x
branch
4 times, most recently
from
May 1, 2024 10:54
3fa6235
to
41695ac
Compare
renovate
bot
changed the title
chore(deps): update rust crate winit to 0.30
chore(deps): update rust crate winit to 0.30.0
May 1, 2024
renovate
bot
force-pushed
the
renovate/winit-0.x
branch
from
May 5, 2024 10:59
41695ac
to
01ea655
Compare
renovate
bot
changed the title
chore(deps): update rust crate winit to 0.30.0
chore(deps): update rust crate winit to 0.30
May 5, 2024
renovate
bot
force-pushed
the
renovate/winit-0.x
branch
7 times, most recently
from
May 14, 2024 05:50
5f7e6e4
to
8601c48
Compare
renovate
bot
force-pushed
the
renovate/winit-0.x
branch
7 times, most recently
from
May 21, 2024 05:53
af6804b
to
78a100e
Compare
renovate
bot
force-pushed
the
renovate/winit-0.x
branch
4 times, most recently
from
May 23, 2024 02:22
2d78bc6
to
a2485ac
Compare
renovate
bot
force-pushed
the
renovate/winit-0.x
branch
4 times, most recently
from
June 1, 2024 17:49
3ae73b1
to
5d9d58d
Compare
renovate
bot
force-pushed
the
renovate/winit-0.x
branch
9 times, most recently
from
October 16, 2024 09:47
b31b752
to
f4c5a03
Compare
renovate
bot
force-pushed
the
renovate/winit-0.x
branch
3 times, most recently
from
October 21, 2024 18:42
283da09
to
a72eb94
Compare
renovate
bot
force-pushed
the
renovate/winit-0.x
branch
2 times, most recently
from
October 29, 2024 18:24
112d35e
to
34e0f11
Compare
renovate
bot
force-pushed
the
renovate/winit-0.x
branch
8 times, most recently
from
November 9, 2024 01:30
adbaa81
to
8867c35
Compare
renovate
bot
force-pushed
the
renovate/winit-0.x
branch
5 times, most recently
from
November 20, 2024 00:33
61b667c
to
c1e2b96
Compare
Based on the migration code in the
use dpi::{LogicalPosition, LogicalSize};
use winit::{
application::ApplicationHandler,
event::WindowEvent,
event_loop::{ActiveEventLoop, EventLoop},
window::{Window, WindowId},
};
use wry::{Rect, WebViewBuilder};
#[derive(Default)]
struct State {
window: Option<Window>,
webview: Option<wry::WebView>,
}
impl ApplicationHandler for State {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
let mut attributes = Window::default_attributes();
attributes.inner_size = Some(LogicalSize::new(800, 800).into());
let window = event_loop.create_window(attributes).unwrap();
let webview = WebViewBuilder::new()
.with_url("https://tauri.app")
.build_as_child(&window)
.unwrap();
self.window = Some(window);
self.webview = Some(webview);
}
fn window_event(
&mut self,
_event_loop: &ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {
match event {
WindowEvent::Resized(size) => {
let window = self.window.as_ref().unwrap();
let webview = self.webview.as_ref().unwrap();
let size = size.to_logical::<u32>(window.scale_factor());
webview
.set_bounds(Rect {
position: LogicalPosition::new(0, 0).into(),
size: LogicalSize::new(size.width, size.height).into(),
})
.unwrap();
}
WindowEvent::CloseRequested => {
std::process::exit(0);
}
_ => {}
}
}
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
{
while gtk::events_pending() {
gtk::main_iteration_do(false);
}
}
}
}
fn main() -> wry::Result<()> {
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
{
use gtk::prelude::DisplayExtManual;
gtk::init().unwrap();
if gtk::gdk::Display::default().unwrap().backend().is_wayland() {
panic!("This example doesn't support wayland!");
}
winit::platform::x11::register_xlib_error_hook(Box::new(|_display, error| {
let error = error as *mut x11_dl::xlib::XErrorEvent;
(unsafe { (*error).error_code }) == 170
}));
}
let event_loop = EventLoop::new().unwrap();
let mut state = State::default();
event_loop.run_app(&mut state).unwrap();
Ok(())
}
use std::borrow::Cow;
use std::sync::Arc;
use winit::{
application::ApplicationHandler,
event::WindowEvent,
event_loop::{ActiveEventLoop, EventLoop},
window::{Window, WindowId},
};
use wry::{
dpi::{LogicalPosition, LogicalSize},
Rect, WebViewBuilder,
};
#[derive(Default)]
struct State {
window: Option<Arc<Window>>,
webview: Option<wry::WebView>,
gfx_state: Option<GfxState>,
}
struct GfxState {
surface: wgpu::Surface<'static>,
device: wgpu::Device,
queue: wgpu::Queue,
config: wgpu::SurfaceConfiguration,
render_pipeline: wgpu::RenderPipeline,
}
impl GfxState {
fn new(window: Arc<Window>) -> Self {
let instance = wgpu::Instance::default();
let window_size = window.inner_size();
let surface = instance.create_surface(window).unwrap();
let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
force_fallback_adapter: false,
compatible_surface: Some(&surface),
}))
.expect("Failed to find an appropriate adapter");
let (device, queue) = pollster::block_on(adapter.request_device(
&wgpu::DeviceDescriptor {
label: None,
required_features: wgpu::Features::empty(),
required_limits:
wgpu::Limits::downlevel_webgl2_defaults().using_resolution(adapter.limits()),
},
None,
))
.expect("Failed to create device");
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(
r#"
@vertex
fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> {
let x = f32(i32(in_vertex_index) - 1);
let y = f32(i32(in_vertex_index & 1u) * 2 - 1);
return vec4<f32>(x, y, 0.0, 1.0);
}
@fragment
fn fs_main() -> @location(0) vec4<f32> {
return vec4<f32>(1.0, 0.0, 0.0, 1.0);
}
"#,
)),
});
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[],
push_constant_ranges: &[],
});
let swapchain_capabilities = surface.get_capabilities(&adapter);
let swapchain_format = swapchain_capabilities.formats[0];
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: Some(&pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
buffers: &[],
compilation_options: Default::default(),
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
targets: &[Some(swapchain_format.into())],
compilation_options: Default::default(),
}),
primitive: wgpu::PrimitiveState::default(),
depth_stencil: None,
multisample: wgpu::MultisampleState::default(),
multiview: None,
});
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: swapchain_format,
width: window_size.width,
height: window_size.height,
present_mode: wgpu::PresentMode::Fifo,
desired_maximum_frame_latency: 2,
alpha_mode: swapchain_capabilities.alpha_modes[0],
view_formats: vec![],
};
surface.configure(&device, &config);
Self {
surface,
device,
queue,
config,
render_pipeline,
}
}
fn render(&mut self) {
let frame = self
.surface
.get_current_texture()
.expect("Failed to acquire next swap chain texture");
let view = frame
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
{
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
store: wgpu::StoreOp::Store,
},
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
});
render_pass.set_pipeline(&self.render_pipeline);
render_pass.draw(0..3, 0..1);
}
self.queue.submit(Some(encoder.finish()));
frame.present();
}
}
impl ApplicationHandler for State {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
let mut attributes = Window::default_attributes();
attributes.transparent = true;
let window = Arc::new(event_loop.create_window(attributes).unwrap());
let gfx_state = GfxState::new(Arc::clone(&window));
let webview = WebViewBuilder::new()
.with_bounds(Rect {
position: LogicalPosition::new(100, 100).into(),
size: LogicalSize::new(200, 200).into(),
})
.with_transparent(true)
.with_html(
r#"<html>
<body style="background-color:rgba(87,87,87,0.5);"></body>
<script>
window.onload = function() {
document.body.innerText = `hello, ${navigator.userAgent}`;
};
</script>
</html>"#,
)
.build_as_child(&window)
.unwrap();
window.request_redraw();
self.window = Some(window);
self.webview = Some(webview);
self.gfx_state = Some(gfx_state);
}
fn window_event(
&mut self,
_event_loop: &ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {
match event {
WindowEvent::Resized(size) => {
if let Some(gfx_state) = &mut self.gfx_state {
gfx_state.config.width = size.width;
gfx_state.config.height = size.height;
gfx_state
.surface
.configure(&gfx_state.device, &gfx_state.config);
if let Some(window) = &self.window {
window.request_redraw();
}
}
}
WindowEvent::RedrawRequested => {
if let Some(gfx_state) = &mut self.gfx_state {
gfx_state.render();
}
}
WindowEvent::CloseRequested => {
std::process::exit(0);
}
_ => {}
}
}
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
{
while gtk::events_pending() {
gtk::main_iteration_do(false);
}
}
}
}
fn main() {
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
{
use gtk::prelude::DisplayExtManual;
gtk::init().unwrap();
if gtk::gdk::Display::default().unwrap().backend().is_wayland() {
panic!("This example doesn't support wayland!");
}
winit::platform::x11::register_xlib_error_hook(Box::new(|_display, error| {
let error = error as *mut x11_dl::xlib::XErrorEvent;
(unsafe { (*error).error_code }) == 170
}));
}
let event_loop = EventLoop::new().unwrap();
let mut state = State::default();
event_loop.run_app(&mut state).unwrap();
}
use winit::{
application::ApplicationHandler,
event::WindowEvent,
event_loop::{ActiveEventLoop, EventLoop},
window::{Window, WindowId},
};
use wry::{
dpi::{LogicalPosition, LogicalSize},
Rect, WebViewBuilder,
};
#[derive(Default)]
struct State {
window: Option<Window>,
webview1: Option<wry::WebView>,
webview2: Option<wry::WebView>,
webview3: Option<wry::WebView>,
webview4: Option<wry::WebView>,
}
impl ApplicationHandler for State {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
let mut attributes = Window::default_attributes();
attributes.inner_size = Some(LogicalSize::new(800, 800).into());
let window = event_loop.create_window(attributes).unwrap();
let size = window.inner_size().to_logical::<u32>(window.scale_factor());
let webview1 = WebViewBuilder::new()
.with_bounds(Rect {
position: LogicalPosition::new(0, 0).into(),
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
})
.with_url("https://tauri.app")
.build_as_child(&window)
.unwrap();
let webview2 = WebViewBuilder::new()
.with_bounds(Rect {
position: LogicalPosition::new(size.width / 2, 0).into(),
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
})
.with_url("https://github.com/tauri-apps/wry")
.build_as_child(&window)
.unwrap();
let webview3 = WebViewBuilder::new()
.with_bounds(Rect {
position: LogicalPosition::new(0, size.height / 2).into(),
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
})
.with_url("https://twitter.com/TauriApps")
.build_as_child(&window)
.unwrap();
let webview4 = WebViewBuilder::new()
.with_bounds(Rect {
position: LogicalPosition::new(size.width / 2, size.height / 2).into(),
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
})
.with_url("https://google.com")
.build_as_child(&window)
.unwrap();
self.window = Some(window);
self.webview1 = Some(webview1);
self.webview2 = Some(webview2);
self.webview3 = Some(webview3);
self.webview4 = Some(webview4);
}
fn window_event(
&mut self,
_event_loop: &ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {
match event {
WindowEvent::Resized(size) => {
if let (Some(window), Some(webview1), Some(webview2), Some(webview3), Some(webview4)) = (
&self.window,
&self.webview1,
&self.webview2,
&self.webview3,
&self.webview4,
) {
let size = size.to_logical::<u32>(window.scale_factor());
webview1
.set_bounds(Rect {
position: LogicalPosition::new(0, 0).into(),
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
})
.unwrap();
webview2
.set_bounds(Rect {
position: LogicalPosition::new(size.width / 2, 0).into(),
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
})
.unwrap();
webview3
.set_bounds(Rect {
position: LogicalPosition::new(0, size.height / 2).into(),
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
})
.unwrap();
webview4
.set_bounds(Rect {
position: LogicalPosition::new(size.width / 2, size.height / 2).into(),
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
})
.unwrap();
}
}
WindowEvent::CloseRequested => {
std::process::exit(0);
}
_ => {}
}
}
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
{
while gtk::events_pending() {
gtk::main_iteration_do(false);
}
}
}
}
fn main() -> wry::Result<()> {
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
{
use gtk::prelude::DisplayExtManual;
gtk::init()?;
if gtk::gdk::Display::default().unwrap().backend().is_wayland() {
panic!("This example doesn't support wayland!");
}
winit::platform::x11::register_xlib_error_hook(Box::new(|_display, error| {
let error = error as *mut x11_dl::xlib::XErrorEvent;
(unsafe { (*error).error_code }) == 170
}));
}
let event_loop = EventLoop::new().unwrap();
let mut state = State::default();
event_loop.run_app(&mut state).unwrap();
Ok(())
} |
renovate
bot
force-pushed
the
renovate/winit-0.x
branch
from
December 10, 2024 12:44
c1e2b96
to
278f237
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
0.29
->0.30
Release Notes
rust-windowing/winit (winit)
v0.30.5
: Winit version 0.30.5Compare Source
Added
ActiveEventLoop::system_theme()
, returning the current system theme.Error
forplatform::web::CustomCursorError
.{Active,}EventLoopExtAndroid::android_app()
to access the app used to create the loop.Fixed
feature = "rwh_04"
.WindowEvent::Cursor*
.Window::theme()
if no theme override is set.v0.30.4
: Winit version 0.30.4Compare Source
Changed
DeviceId::dummy()
andWindowId::dummy()
are no longer markedunsafe
.Fixed
WindowEvent::Resized
not usingrequestAnimationFrame
when sendingWindowEvent::RedrawRequested
and also potentially causingWindowEvent::RedrawRequested
to not be de-duplicated.
v0.30.3
: Winit version 0.30.3Compare Source
Added
EventLoopExtWebSys::(set_)poll_strategy()
to allow settingcontrol flow strategies before starting the event loop.
WaitUntilStrategy
, which allows to set different strategies forControlFlow::WaitUntil
. By default the Prioritized Task Scheduling API isused, with a fallback to
setTimeout()
with a trick to circumvent throttlingto 4ms. But an option to use a Web worker to schedule the timer is available
as well, which commonly prevents any throttling when the window is not focused.
Changed
NSWindow
instead of application-wide.Fixed
WindowBuilder::with_theme
not having any effect on the window.v0.30.2
: Winit version 0.30.2Compare Source
Fixed
EventLoopProxy::send_event()
triggering event loop immediatelywhen not called from inside the event loop. Now queues a microtask instead.
CursorIcon::Default
.InnerSizeWriter::request_inner_size()
.v0.30.1
: Winit version 0.30.1Compare Source
Added
raw-window-handle
versions 0.4 and 0.5 asraw_window_handle_04
andraw_window_handle_05
.ApplicationHandler
for&mut
references and heap allocations to something that implementsApplicationHandler
.EventLoopExtWayland
andEventLoopExtX11
, providing methodsis_wayland
andis_x11
onEventLoop
.Fixed
Ime::Preedit
.v0.30.0
: Winit version 0.30.0Compare Source
Added
OwnedDisplayHandle
type for allowing safe display handle usage outside oftrivial cases.
ApplicationHandler<T>
trait which mimicsEvent<T>
.WindowBuilder::with_cursor
andWindow::set_cursor
which takes aCursorIcon
orCustomCursor
.Sync
implementation forEventLoopProxy<T: Send>
.Window::default_attributes
to get defaultWindowAttributes
.EventLoop::builder
to getEventLoopBuilder
without export.CustomCursor::from_rgba
to allow creating cursor images from RGBA data.CustomCursorExtWebSys::from_url
to allow loading cursor images from URLs.CustomCursorExtWebSys::from_animation
to allow creating animatedcursors from other
CustomCursor
s.{Active,}EventLoop::create_custom_cursor
to load custom cursor image sources.ActiveEventLoop::create_window
andEventLoop::create_window
.CustomCursor
which could be set viaWindow::set_cursor
, implemented onWindows, macOS, X11, Wayland, and Web.
Event.preventDefault()
onWindow
.PinchGesture
,DoubleTapGesture
,PanGesture
andRotationGesture
.UIGestureRecognizerDelegate
for fine grained control of gesture recognizers.with_title_text_color
, andwith_corner_preference
onWindowAttributesExtWindows
.AnyThread
API to access window handle off the main thread.Changed
1.65
to1.70
.sctk-adwaita
to0.9.0
, which changed system librarycrates. This change is a cascading breaking change, you must do breaking
change as well, even if you don't expose winit.
TouchpadMagnify
toPinchGesture
.SmartMagnify
toDoubleTapGesture
.TouchpadRotate
toRotationGesture
.EventLoopWindowTarget
toActiveEventLoop
.platform::x11::XWindowType
toplatform::x11::WindowType
.VideoMode
toVideoModeHandle
to represent that it doesn't holdstatic data.
Debug
formatting ofWindowId
more concise.dpi
types to its own crate, and re-export it from the root crate.log
withtracing
, uselog
feature ontracing
to restore oldbehavior.
EventLoop::with_user_event
now returnsEventLoopBuilder
.HandleError::Unavailable
when a window handle is not available.RawWindowHandle::WebCanvas
instead ofRawWindowHandle::Web
.HandleError::Unavailable
when a window handle is not available.HandleError::Unavailable
when a window handle is not available.WS_CAPTION
,WS_BORDER
, andWS_EX_WINDOWEDGE
stylesfor child windows without decorations.
ndk
to0.9.0
andandroid-activity
to0.6.0
,and remove unused direct dependency on
ndk-sys
.Deprecated
Deprecate
EventLoop::run
, useEventLoop::run_app
.Deprecate
EventLoopExtRunOnDemand::run_on_demand
, useEventLoop::run_app_on_demand
.Deprecate
EventLoopExtPumpEvents::pump_events
, useEventLoopExtPumpEvents::pump_app_events
.The new
app
APIs accept a newly addedApplicationHandler<T>
instead ofFn
. The semantics are mostly the same, given that the capture list of theclosure is your new
State
. Consider the following code:To migrate this code, you should move all the captured values into some
newtype
State
and implementApplicationHandler
for this type. Finally,we move particular
match event
arms into methods onApplicationHandler
,for example:
Please submit your feedback after migrating in this issue.
Deprecate
Window::set_cursor_icon
, useWindow::set_cursor
.Removed
Remove
Window::new
, useActiveEventLoop::create_window
instead.You now have to create your windows inside the actively running event loop
(usually the
new_events(cause: StartCause::Init)
orresumed()
events),and can no longer do it before the application has properly launched.
This change is done to fix many long-standing issues on iOS and macOS, and
will improve things on Wayland once fully implemented.
To ease migration, we provide the deprecated
EventLoop::create_window
thatwill allow you to bypass this restriction in this release.
Using the migration example from above, you can change your code as follows:
Remove
Deref
implementation forEventLoop
that gaveEventLoopWindowTarget
.Remove
WindowBuilder
in favor ofWindowAttributes
.Remove Generic parameter
T
fromActiveEventLoop
.Remove
EventLoopBuilder::with_user_event
, useEventLoop::with_user_event
.Remove Redundant
EventLoopError::AlreadyRunning
.Remove
WindowAttributes::fullscreen
and expose as field directly.On X11, remove
platform::x11::XNotSupported
export.Fixed
Configuration
📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.