How to hard reset to previous commit in libgit2? - c++

My program (which uses libgit2) makes a commit to local repo (no push, only commit), then does something and then, according to the result, tries to revert the last commit by resetting repo to HEAD~1 (one commit before HEAD). Simply hard reset.
The problem: the code below does reset HEAD to HEAD~1, but leaves all changes between these 2 commit as "staged", while I need to simply erase these changes. What am I doing wrong?
bool RevertLastCommit(std::string &errorMessage)
{
int error;
git_object *head_commit_obj = nullptr;
error = git_revparse_single(&head_commit_obj, repo, "HEAD~1");
if (error < 0)
{
return false;
}
git_commit *head_commit = (git_commit *)head_commit_obj;
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
int reset_result = git_reset(repo, const_cast<git_object *>(head_commit_obj), GIT_RESET_HARD, &opts);
if (reset_result < 0) {
printf("Reset failed!\n");
return false;
}
printf("Done reverting\n");
error = git_checkout_head(repo, &opts);
if (error < 0)
{
return false;
}
printf("Hard checkout\n");
return true;
}

Related

Calling next multiple times in loop causes stack overflow in ue4 Lua machine

I've been working on lua machine json object system. But I've hit a snag with the json object merger(You can see the functions code used below). When I try to iterate through a table using a while loop and IterateTable function, and then ether call Next or a function containing Next it causes an infinite loop that leads to a stack overflow crash.
Loops through the map elements of a user data object
void UJsonMergetFunctionLibrary::MergeLuaJsonObject(UMyDynamicObject* Origional, UMyDynamicObject* ToMerge, bool Override)
{
//Get all user data object keys
for (TPair<FString, FLuaValue>& P: ToMerge->GetTableContent())
{
//Holds the value of current key
FLuaValue Hold;
if (Origional->hasField(P.Key))
{
if ((P.Value.Type == ELuaValueType::Table) || (P.Value.Type == ELuaValueType::UObject))
{
Hold = Origional->LuaGetField(P.Key);
MergeLuaJsonObject(Hold, P.Value, Override);
}
else if (Override)
{
Origional->LuaSetField(P.Key, P.Value);
}
}
else
{
Origional->LuaSetField(P.Key, P.Value);
}
}
}
Loops through the elements of ether a lua table or user data object
void UJsonMergetFunctionLibrary::MergeLuaJsonObject(FLuaValue& Origional, FLuaValue& ToMerge, bool Override)
{
if (Origional.Type != ToMerge.Type) {
if (Override)
{
Origional = ToMerge;
return;
}
else
{
return;
}
}
//Table
if ((Origional.Type == ELuaValueType::Table) || (ToMerge.Type == ELuaValueType::Table)) {
TPair<FLuaValue, FLuaValue> Pair;
int32 MaxDex = MaxTableIndex(Origional);
while (IterateTable(ToMerge, Pair)) {
if (Pair.Key.Type == ELuaValueType::Integer)
{
MaxDex += 1;
Origional.SetFieldByIndex(MaxDex, Pair.Value);
}
else if (HasTableField(Origional, Pair.Key.ToString()))
{
FLuaValue Hold = Origional.GetField(Pair.Key.ToString());
if ((Pair.Value.Type == ELuaValueType::Table) && (Hold.Type == ELuaValueType::Table))
{
//Hold = OrigionalObj->LuaGetField(P.Key);
MergeLuaJsonObject(Hold, Pair.Value, Override);
}
else if((Pair.Value.Type == ELuaValueType::UObject) && (Hold.Type == ELuaValueType::UObject))
{
MergeLuaJsonObject(Hold, Pair.Value, Override);
}
else if (Override) {
Origional.SetField(Pair.Key.ToString(), Pair.Value);
}
}
else
{
Origional.SetField(Pair.Key.ToString(), Pair.Value);
}
}
}
//Object
else if ((Origional.Type == ELuaValueType::UObject) || (ToMerge.Type == ELuaValueType::UObject)) {
UMyDynamicObject* ToMergeObj = Cast<UMyDynamicObject>(ULuaBlueprintFunctionLibrary::Conv_LuaValueToObject(ToMerge));
UMyDynamicObject* OrigionalObj = Cast<UMyDynamicObject>(ULuaBlueprintFunctionLibrary::Conv_LuaValueToObject(Origional));
TMap<FString, FLuaValue> Keys = ToMergeObj->GetTableContent();
for (TPair<FString, FLuaValue>& P: Keys)
{
FLuaValue Hold;
if (OrigionalObj->hasField(P.Key))
{
if ((P.Value.Type == ELuaValueType::Table) || (P.Value.Type == ELuaValueType::UObject))
{
Hold = OrigionalObj->LuaGetField(P.Key);
MergeLuaJsonObject(Hold, P.Value, Override);
}
else if (Override)
{
OrigionalObj->LuaSetField(P.Key, P.Value);
}
}
else
{
OrigionalObj->LuaSetField(P.Key, P.Value);
}
//OrigionalObj->LuaSetField(P.Key, P)
}
Origional = FLuaValue(OrigionalObj);
}
}
Iterates and retrieves the next key in a table
bool UJsonMergetFunctionLibrary::IterateTable(FLuaValue Table, TPair<FLuaValue, FLuaValue>& Pair)
{
if (Table.Type != ELuaValueType::Table)
return false;
ULuaState* L = Table.LuaState;
if (!L)
return false;
if (Pair.Key.IsNil())
{
L->FromLuaValue(Table);
L->PushNil(); // first key
}
if (L->Next(-2))
{
Pair.Key = L->ToLuaValue(-2);
Pair.Value = L->ToLuaValue(-1);
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, Pair.Key.ToString());
L->Pop(); // pop the value
return true;
}
else
{
L->Pop(); // pop the table
return false;
}
}
Checks if the table contains a key
bool UJsonMergetFunctionLibrary::HasTableField(FLuaValue Table, FString FieldName)
{
if (Table.Type != ELuaValueType::Table)
return false;
ULuaState* L = Table.LuaState;
if (!L)
return false;
L->FromLuaValue(Table);
L->PushNil(); // first key
while (L->Next(-2))
{
FLuaValue Key = L->ToLuaValue(-2);
if (Key.ToString() == FieldName)
{
L->Pop(); // pop the value
L->Pop(); // pop the table
return true;
}
else {
L->Pop(); // pop the value
}
}
L->Pop(); // pop the table
return false;
}
1.I have tried poping both the value and the key when calling next within the loop, and than reassigning the old key once the internal next call ends.
2.I have tried googling it and Wasn't able to find anything.
3.I added a limit to how many times the loop can execute, to test if a infinite loops is causing the crash.
4.I tried making a function in pure lua that loops through a table and calls next within it(Didn't work, but do note I'm new to lua).
None of what I've tried has worked. What I want to happen is that when both Original and ToMerge have the same key, and the value assigned to that key is table I want it to perform recursion and merge those two tables than once thats done return to the execution on the original loop. Any help would be appreciated.

MariaDB Connector C, mysql_stmt_fetch_column() and memory corruption

I'm working on a wrapper for MariaDB Connector C. There is a typical situation when a developer doesn't know a length of a data stored in a field. As I figured out, one of the ways to obtain a real length of the field is to pass a buffer of lengths to mysql_stmt_bind_result and then to fetch each column by calling mysql_stmt_fetch_column. But I can't understand how the function mysql_stmt_fetch_column works because I'm getting a memory corruption and app abortion.
Here is how I'm trying to reach my goal
// preparations here
...
if (!mysql_stmt_execute(stmt))
{
int columnNum = mysql_stmt_field_count(stmt);
if (columnNum > 0)
{
MYSQL_RES* metadata = mysql_stmt_result_metadata(stmt);
MYSQL_FIELD* fields = mysql_fetch_fields(metadata);
MYSQL_BIND* result = new MYSQL_BIND[columnNum];
std::memset(result, 0, sizeof (MYSQL_BIND) * columnNum);
std::vector<unsigned long> lengths;
lengths.resize(columnNum);
for (int i = 0; i < columnNum; ++i)
result[i].length = &lengths[i];
if (!mysql_stmt_bind_result(stmt, result))
{
while (true)
{
int status = mysql_stmt_fetch(stmt);
if (status == 1)
{
m_lastError = mysql_stmt_error(stmt);
isOK = false;
break;
}
else if (status == MYSQL_NO_DATA)
{
isOK = true;
break;
}
for (int i = 0; i < columnNum; ++i)
{
my_bool isNull = true;
if (lengths.at(i) > 0)
{
result[i].buffer_type = fields[i].type;
result[i].is_null = &isNull;
result[i].buffer = malloc(lengths.at(i));
result[i].buffer_length = lengths.at(i);
mysql_stmt_fetch_column(stmt, result, i, 0);
if (!isNull)
{
// here I'm trying to read a result and I'm getting a valid result only from the first column
}
}
}
}
}
}
If I put an array to the mysql_stmt_fetch_column then I'm fetching the only first field valid, all other fields are garbage. If I put a single MYSQL_BIND structure to this function, then I'm getting an abortion of the app on approximately 74th field (funny thing that it's always this field). If I use another array of MYSQL_BIND then the situation is the same as the first case.
Please help me to understand how to use it correctly! Thanks
Minimal reproducible example

Code runs fine with WinDbg but weird without it

I am debugging an issue with WinDbg which I can consistently produce. The problem is when I run the executable with WinDbg to debug it, the issue can't be reproduced. What could be the reason?
Here is the code the behaves differently:
CWnd* pWnd = GetDlgItem(IDOKCANCEL);
if(pWnd)
{
CString sOK;
sOK.LoadString(IDS_OK);
pWnd->SetWindowText(sOK);
}
Here the button text is updated properly when I run with WinDbg but it is not updated when I run it normally (which is the bug).
Update
Like I said in comments, the issue is not with the code above because it's doesn't even get called. The operation is done in a worker thread which sends update messages to this dialog. The final message that executes the above code is never send do it so the above code is never executed.
Why the worker thread doesn't send this message is interesting. It ges locked on a critical section while opening a database. WinDbg tells me that the main thread is the owner of that critical section but I can't see from call stack or any other way where does it failed to unlock the critical section.
What complicates the problem is that it works fine if I run it with debugger. I added log output but it also starts to works fine with this change.
The only way I can catch it with a debugger is when I run it normal mode, produce the problem, then attach the debugger and it shows me its locked on the critical section. It shows the main thread is the owner of that critical section but it not clear why it is in locked state. The critical section is simply locked and unlocked in one function and its out of there.
Update 2
I am using the critical section only in one file in my entire project and there in only two functions (when it opens database and recordset).
BOOL CADODatabase::Open(LPCTSTR lpstrConnection, LPCTSTR lpstrUserID, LPCTSTR lpstrPassword)
{
CString database = GetSourceDatabase( lpstrConnection, NULL );
// get the appropriate critical section based on database
g_dbCriticalSection = GetDbCriticalSection( database );
if( g_dbCriticalSection)
g_dbCriticalSection->Lock();
HRESULT hr = S_OK;
if(IsOpen())
Close();
if(wcscmp(lpstrConnection, _T("")) != 0)
m_strConnection = lpstrConnection;
ASSERT(!m_strConnection.IsEmpty());
try
{
if(m_nConnectionTimeout != 0)
m_pConnection->PutConnectionTimeout(m_nConnectionTimeout);
hr = m_pConnection->Open(_bstr_t(m_strConnection), _bstr_t(lpstrUserID), _bstr_t(lpstrPassword), NULL);
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
return hr == S_OK;
}
catch(_com_error &e)
{
dump_com_error(e);
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
return FALSE;
}
}
The 2nd function has other visible imperfections but please ignore that, its legacy code.
BOOL CADORecordset::Open(_ConnectionPtr mpdb, LPCTSTR lpstrExec, int nOption)
{
BSTR bstrConnString;
m_pConnection->get_ConnectionString(&bstrConnString);
CString database = GetSourceDatabase( bstrConnString, m_pConnection );
g_dbCriticalSection = GetDbCriticalSection( database );
if( g_dbCriticalSection)
g_dbCriticalSection->Lock();
Close();
if(wcscmp(lpstrExec, _T("")) != 0)
m_strQuery = lpstrExec;
ASSERT(!m_strQuery.IsEmpty());
if(m_pConnection == NULL)
m_pConnection = mpdb;
m_strQuery.TrimLeft();
BOOL bIsSelect = m_strQuery.Mid(0, _tcslen(_T("Select "))).CompareNoCase(_T("select ")) == 0 && nOption == openUnknown;
int maxRetries = 10;
bool bContinue = true;
CursorTypeEnum adCursorType = adOpenStatic;
if (!m_bSQLEngine)
{
// MDB Engine
adCursorType = adOpenStatic;
m_pConnection->CursorLocation = adUseClient;
}
else
{
// SQL Engine
adCursorType = adOpenDynamic;
m_pConnection->CursorLocation = adUseServer;
}
int currentCommandTimeout = m_pConnection->CommandTimeout;
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
for (int iRetry = 0; (iRetry < maxRetries) && bContinue; iRetry++)
{
try
{
// we just use an auto lock object so it is unlocked automatically, it uses same
// critical section object.
if( g_dbCriticalSection)
g_dbCriticalSection->Lock();
int newCommandTimeout = currentCommandTimeout + 15 * iRetry;
m_pConnection->CommandTimeout = newCommandTimeout;
if(bIsSelect || nOption == openQuery || nOption == openUnknown)
{
m_pRecordset->Open((LPCTSTR)m_strQuery, _variant_t((IDispatch*)mpdb, TRUE),
adCursorType, adLockOptimistic, adCmdUnknown);
}
else if(nOption == openTable)
{
m_pRecordset->Open((LPCTSTR)m_strQuery, _variant_t((IDispatch*)mpdb, TRUE),
adOpenDynamic, adLockOptimistic, adCmdTable);
}
else if(nOption == openStoredProc)
{
m_pCmd->ActiveConnection = mpdb;
m_pCmd->CommandText = _bstr_t(m_strQuery);
m_pCmd->CommandType = adCmdStoredProc;
m_pRecordset = m_pCmd->Execute(NULL, NULL, adCmdText);
}
else
{
TRACE( _T("Unknown parameter. %d"), nOption);
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
return FALSE;
}
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
bContinue = false;
}
catch(_com_error &e)
{
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
dump_com_error_without_exception(e, _T("Open"));
// retry Query timeout
CString szDescription;
_bstr_t bstrDescription(e.Description());
szDescription.Format( _T("%s"), (LPCTSTR)bstrDescription);
if ((szDescription.Find(_T("Query timeout expired")) == -1) || (iRetry == maxRetries - 1))
{
m_pConnection->CommandTimeout = currentCommandTimeout;
throw CADOException(e.Error(), e.Description());
}
Sleep (1000);
bContinue = true;
}
}
m_pConnection->CommandTimeout = currentCommandTimeout;
return m_pRecordset != NULL && m_pRecordset->GetState()!= adStateClosed;
}
For the sake of completeness, the above calls this function:
static CCriticalSection* GetDbCriticalSection(const CString& database)
{
// For now we only care about one database and its corresponding critical section
if (database.CompareNoCase( _T("Alr") ) == 0)
return &g_csAlrDb; // g_csAlrDb is defined static global in this file
else
return 0;
}
The Open() function gets called for various databases, I am only locking guarding access to one database. As you can see there is corresponding lock/unlocks so not sure how does code comes up of these functions leave th critical section locked. Could it be because of MFC issue?
In my case, most of the time, when C++ software behaves different between debug and release versions, it's because of uninitialized variables, different libraries linked, or compiler optimizations backfiring.
To trace the bug, try evaluating variables and function return values, i.e. LoadString, for example with AfxMessageBox().

xcb key repeat ignoring not working

I have been trying to figure out how to ignore repeated keys in an xcb event loop and so far have got this:
extern xcb_connection_t *connection;
// looks like there's a leak, but in the finished product there isn't
bool poll_event(/*my_event_type e*/){
static xcb_generic_event_t *ev = nullptr;
static xcb_key_press_event_t *last_key_ev = nullptr;
if(!(ev = xcb_poll_for_event(connection)))
return false;
switch(ev->response_type & ~0x80){
case XCB_KEY_PRESS:{
xcb_key_press_event_t *kp = static_cast<decltype(kp)>(ev);
if(last_key_ev &&
((last_key_ev->response_type & ~0x80) == XCB_KEY_RELEASE) &&
(last_key_ev->detail == kp->detail) &&
(last_key_ev->time == kp->time)
){
std::free(last_key_ev);
last_key_ev = kp;
// is repeated key, ignore this event
return false;
}
std::free(last_key_ev);
last_key_ev = kp;
return true;
}
case XCB_KEY_RELEASE:{
/* same as KEY_PRESS but looking for KEY_PRESS in 'last_key_ev' */
}
default:
std::free(ev);
return true;
}
}
This doesn't work because it will only discard the second half of the repeated event pair (XCB_KEY_RELEASE then XCB_KEY_PRESS), so I get a bunch of XCB_KEY_RELEASE events rather than none. but there doesn't seem to be a function in xcb for testing if there is an event in the queue without modifying the queue itself.
I am looking for an XEventsQueued equivalent in xcb so I could test if there is an event queued straight afterward instead of using the last event that occured, but have failed to do so yet.
Have any of you done this already and be willing to pass on your wisdom in the matter?
So, #n.m said that XCB has no utility for peaking into the event queue. So I wrote my own wrapper over the xcb event queue so I could peak into the next event. Here is how I implemented it if anyone is interested:
First my event queue:
extern xcb_connection_t *connection;
struct my_event_queue_t{
xcb_generic_event_t *prev = nullptr;
xcb_generic_event_t *current = nullptr;
xcb_generic_event_t *next = nullptr;
} event_queue;
void update_event_queue(){
std::free(event_queue.prev);
event_queue.prev = event_queue.current;
event_queue.current = event_queue.next;
event_queue.next = xcb_poll_for_queued_event(connection);
}
Then the event loop:
struct my_event_type;
bool poll_event(my_event_type &ret){
static xcb_generic_event_t *xcb_ev = nullptr;
update_event_queue();
xcb_ev = event_queue.current;
if(!xcb_ev) return false;
switch(xcb_ev->response_type & ~0x80){
case XCB_KEY_RELEASE:{
static xcb_key_press_event_t *kp = nullptr;
kp = xcb_ev;
if(event_queue.next &&
((event_queue->response_type & ~0x80) == XCB_KEY_PRESS) &&
(reinterpret_cast<decltype(kp)>(xcb_ev)->time == kp->time) &&
(reinterpret_cast<decltype(kp)>(xcb_ev)->detail == kp->detail)
){
update_event_queue(); // eat repeat event
return false;
}
// update ret
return true;
}
case XCB_KEY_PRESS:{
// handle normally
// update ret
return true;
}
default:
// signify unknown event
return true;
}
}
This is how I ignore key repeats in my application, which is a toolkit for game/graphical application development. I haven't tested what sort of performance dip this gives, but it should be minimal.

Dartium build error in Release mode

I was following http://code.google.com/p/dart/wiki/BuildingDartium#Build and attempted to build dartium in Release mode and encountered the following error:
$ ./dartium_tools/build.py --mode=Release
.
.
.
CXX(target) out/Release/obj.target/webrtc_video_coding/third_party/webrtc/modules/video_coding/main/source/rtt_filter.o
CXX(target) out/Release/obj.target/webrtc_video_coding/third_party/webrtc/modules/video_coding/main/source/session_info.o
CXX(target) out/Release/obj.target/webrtc_video_coding/third_party/webrtc/modules/video_coding/main/source/timestamp_extrapolator.o
third_party/webrtc/modules/video_coding/main/source/session_info.cc: In member function ‘int webrtc::VCMSessionInfo::PrepareForDecode(uint8_t*)’:
third_party/webrtc/modules/video_coding/main/source/session_info.cc:590:8: error: variable ‘previous_lost’ set but not used [-Werror=unused-but-set-variable]
cc1plus: all warnings being treated as errors
make: *** [out/Release/obj.target/webrtc_video_coding/third_party/webrtc/modules/video_coding/main/source/session_info.o] Error 1
make: *** Waiting for unfinished jobs....
Traceback (most recent call last):
File "./dartium_tools/build.py", line 67, in <module>
main()
File "./dartium_tools/build.py", line 64, in main
[target for (target, _) in targets])
File "/home/sangeeth/work/g/dartium/src/dartium_tools/utils.py", line 97, in runCommand
raise Exception('Failed to run command. return code=%s' % p.returncode)
Exception: Failed to run command. return code=2
$
But when I looked at the code dartium/src/third_party/webrtc/modules/video_coding/main/source/session_info.cc::VCMSessionInfo::PrepareForDecode(), I saw the following:
int VCMSessionInfo::PrepareForDecode(uint8_t* frame_buffer) {
int length = SessionLength();
int real_data_bytes = 0;
if (length == 0)
return length;
bool previous_lost = false;
PacketIterator it = packets_.begin();
PacketIterator prev_it = it;
for (; it != packets_.end(); ++it) {
bool packet_loss = ((*prev_it).sizeBytes == 0 ||
!InSequence(it, prev_it));
if ((*it).bits) {
if (prev_it != it) { // Not the first packet.
uint8_t* ptr_first_byte =
const_cast<uint8_t*>((*it).dataPtr);
if (packet_loss) {
// It is be better to throw away this packet if we are
// missing the previous packet.
memset(ptr_first_byte, 0, (*it).sizeBytes);
previous_lost = true;
++packets_not_decodable_;
} else if ((*it).sizeBytes > 0) {
// Glue with previous byte.
// Move everything from [this packet start + 1, end of buffer] one
// byte to the left.
uint8_t* ptr_prev_byte =
const_cast<uint8_t*>((*prev_it).dataPtr) +
(*prev_it).sizeBytes - 1;
*ptr_prev_byte = (*ptr_prev_byte) | (*ptr_first_byte);
memmove(const_cast<uint8_t*>((*it).dataPtr),
(*it).dataPtr + 1, (*it).sizeBytes - 1);
ShiftSubsequentPackets(it, -1);
(*it).sizeBytes--;
length--;
previous_lost = false;
real_data_bytes += (*it).sizeBytes;
}
} else {
memset(const_cast<uint8_t*>((*it).dataPtr), 0,
(*it).sizeBytes);
previous_lost = true;
++packets_not_decodable_;
}
} else if (packet_loss &&
(*it).codecSpecificHeader.codec == kRTPVideoH263) {
// Pad H.263 packet losses with 10 zeros to make it easier
// for the decoder.
const int kPaddingLength = 10;
WebRtc_UWord8 padding_data[kPaddingLength] = {0};
// Make a copy of the previous packet.
VCMPacket padding_packet(*it);
++padding_packet.seqNum;
padding_packet.dataPtr = padding_data;
padding_packet.sizeBytes = kPaddingLength;
length += InsertPacket(padding_packet, frame_buffer, false, 0);
previous_lost = true;
} else {
real_data_bytes += (*it).sizeBytes;
previous_lost = false;
}
prev_it = it;
}
if (real_data_bytes == 0) {
// Drop the frame since all it contains are zeros.
for (it = packets_.begin(); it != packets_.end(); ++it)
(*it).sizeBytes = 0;
length = 0;
}
return length;
}
The bool variable previous_lost has been used (set to false and true) at many places.
Any valuable input on how to go about this would be a great help.
Setting a bool to true or false is pointless if you don't then read the value later - in the code you posted, a value for previous_lost is indeed set in several places, but nowhere is the value that's set used to do anything (such as a if (previous_lost) ..., for example). That's what's meant by "used" in this context: a variable is used if its value is read.
Note that this (generally) applies for any type of variable: if I set an int to 42 and don't use it any later calculation, it's not "used" either.
In these cases, the variable is completely redundant - it does nothing useful since it is not used by other code. Generally this kind of warning is meant to indicate that perhaps the code that was supposed to use previous_lost was accidentally omitted (or was removed) and needs to be accounted for. Alternatively, the variable might simply be redundant and can be removed entirely.