17 Kasım 2017 Cuma

TortoiseSVN Notlarım

Giriş
tortoiseSVN ile ilgili aldığım notlar aşağıda. tortoise svn arayüzünde çeşit çeşit renkler kullanılmış. Renklerin manası var ve dikkat etmek gerekiyor.

Yardımcı olsun diye ekran görüntüsünün ekliyorum.

SVN Commitlenen Dosyaları skip list şeklinde saklar.

Blame
Açıklaması şöyle
"A technical term for displaying the origin of lines by version is annotating a controlled file with its "history."
Dosyadaki satırın hangi commit numarası ile değiştirildiğini gösterir. svn ve git blame tabirini kullanıyorlar ancak blame ilk anlam olarak suçlama, ayıplama manasına geldiği için işlevi ifade etmek için bence kötü bir kelime seçimi olmuş.
Branch/Tag
Proje Yapısı
Klasik proje yapısı şöyledir.
http://svn.foo.com/myproject
 >branches
 >tags
  -engCM
  -formalCM
 >trunk
Her proje trunk altında nasıl bir yapı izleyeceğini kendisi belirler. Bazı projeler şöyledir
>trunk
  >development
    -code
    -documents
Branch ne zaman açılır?
Branch genellikle ileride tekrar head ile birleştirilmesi düşünülen kodlar için açılır. Uzun süre branch'ler halinde çalışmak külfet haline gelebilir.

Tag ne zaman atılır?
A point in time on the trunk or branch that you wish to preserve.

Belli bir olgunluktaki kod release edilince tag atılır.
Projemizin URL'si aşağıdaki gibi olsun
url/myproj/trunk/...
Tagleri oluşturmak için
url/myproj/tags/Rev.1.0.0
şeklinde bir dizin açılır. Dizini açmak için Repo Browser'da "Add Folder" menüsü kullanılır.
Eğer dizini önceden oluşturmak istemiyorsa Branch/Tag menüsündeki "To path" alanına yazılarak ta yapabiliriz ancak tag için dizini öncde oluşturmak bence daha  kolay.

Daha sonra TortoiseSVN -> Branch/Tag menüsü tıklanır. "To path" alanını yeni açılan dizini göstereccek şekilde güncelleriz.

Tag işleminde default olarak HEAD'de bulunan dosyalara belirtilen hedefe kopyalanır. Eğer istenirse belli bir revizyon veya local'daki veriler de taglenebilir.

Ara dizinleri oluşturmak için "Create Intermediate folders" işaretlenir. Tag atarken "Switch working copy to new branch/tag" seçili olmamalıdır!

Tag yerine comment atılırsa ne olur?
CVS gibi sistemlerde koda comment atılma yöntemi kullanılıyordu. Aynı yöntemi SVN'de uygulamak iyi değil çünkü comment'lere bakarak tag'lenmiş kodun içinde ne olduğunu görmek bir hayli zor olurdu.

Commit
Commit seçeneğine tıklanınca "non-versioned" dosyaları da listeleme veya listelememe seçeneği mevcut. Commit işleminde genelde bir de açıklama girilir. Bu açıklama sadece kaynak dosya ile ilgili olsa iyi olur. Projenin tasarımıyla ilgili kritik açıklamaları buraya girmek anlamsızdır. Commit işleminin hızlı çalışmasına dikkat etmek gerekir.
Commit Hook
SVN sunucusunda  repository'nin hooks dizinine .bat veya .sh dosyası yazılabilir. pre-commit.bat veya post-commit.bat commit öncesi veya sonrası çalıştırılır.

Check for Modifications
Bazen svn değişiklikleri hemen algılamaz ve Windows'ta simgler kırmızı yeşil görünmez. Check for modifications menüsü ile simgelerin yenilenmesi sağlanır.

Diff
diff en son güncellenen sürümle diskte dosyayı karşılaştırır. Dosya svn'de ilerlemiş olsa bile head ile disk arasındaki farkı göstermez!

Export
Repository, .svn dizinleri olmadan bir başka dizine kopyalanabilir. Böylece kaynak kodları taşımak daha kolay olabilir.

Ignore
Dosya seçilerek "Move to changelist" -> "ignore-on-commit" menüsü tıklanır. Böylece dosyayı yanlışlıkla commitlemeyiz.

Patch
Kendi lokalimizde yaptığımız değişiklikleri commitlemeden başkasına aktarmak için kullanılır. Patch file1 dosyasını file2 haline getirmek için yapılması gereken değişiklikleri içerir. Örneğin file1 dosyasındaki 3. satırı sil, 5. satırdan sonra şunu ekle gibi bilgileri içerir.

Patch dosyası yaratmak için Tortoise Svn'e sağ tıklanır "Create Patch" seçilir. Açılan pencereden değişiklik yaptığımız ve patch dosyasına girmesini istediğimiz dosyaları seçer ve x.patch isimli dosyaya kaydederiz. Bu dosyayı alan kişi bizimle aynı dizine bu dosyayı yerleştirir ve çift tıklar.. Dosyadaki değişiklikler kendi lokaline yansıtılır.
Relocate
Svn Repository başka bir yere taşındıysa (sunucu değişince olabilir) relocate seçeneği ile yeni sunucu URL'si tanıtılır.
Show Log
Yapılan commitler görülür. Koyu renk ile gösterilen versiyon lokalimizde olan versiyonu temsil eder. Koyu renk satır ilk sırada ise lokalimiz svn ile senkronize olmuşuzdur, eğer daha alt sırada ise biz "update" işlemini yaptıktan sonra farklı commitler olmuştur. Yani lokalimiz geriden gelmektedir. "Show log" seçilince eğer doküman geçmişte isim değiştirmişse veya taşınmışsa "Stop on copy/remove" seçeneğini seçilmemişse tüm tarihçeyi gösterir. Seçili ise işleme kadar olan tarihçeyi gösterir.

Update
Sunucudaki dosyaları getirir. Eğer merge edilebilecek dosyalar varsa otomatik olarak merge eder.

Merge eğer iki kişi aynı dosyanın farklı satırlarını değiştirmişse çok kolay. SVN bunu kolaylıkla hallediyor. Merge edilen dosyaya sağ tıklayıp "Compare with working copy" menüsü seçilirse açılan pencerede 3 bölüm görülür.

Theirs
Sol üstteki "Theirs" penceresi SVN'e commitlenmiş dosyayı gösterir. Bu pencerede "-" ile işaretli satırlar benim sürümümde olmayan satırları belirtir.

Mine
Sağ üstteki "Mine" penceresi "Mine" ve "Theirs"'in birleştirilmiş halini gösterir. Benim satırlarım "+", onların satırları ise "-" ile belirtilir.

Merged
En alttaki "Merged" penceresi ise "Mine" ve "Theirs"'in birleştirilmiş halini renkli olarak gösterir.


Eğer dosyalar arasında conflict varsa, kırmızı renk ile gösterir. Conflict olan dosyaya sağ tıklayıp Resolve conflict using 'theirs' seçilirse, sunucudaki dosya doğru kabul edilir ve değişikliklerimizi kaybederiz.

Silinmiş Bir Dosyayı Geri Getirmek (Revert veya Rollback)
Silinmiş bir dosyayı geri getirmek için "Show Log" seçilir. Yapılan commitler listesi üzerinde dolaşılarak silinen dosya bulunur. Dosya seçilerek "Revert changes from this revision" seçilir. Aynı şekilde dosyanın daha önceki halini de geri getirmek mümkün.

Belli bir Revizyona Geri Dönme
SVN/Update to revision... menüsünden eski bir revizyon numarası girilerek, geri dönülebilir. SVN global revizyon numarası tutar. Bir dosya değişse bile dizinin de revizyon numarası değişir.

Yeni Tortoise SVN 1.7 ile .svn dosyaları tarihe karışıyor. Artık metadata working copy'nin root dizinindeki bir sqlite veritabanında tutuluyor. Bu yüzden kurulumda daha eski client'lar working copy ile çalışamaz uyarısı veriliyor.

Dosya Taşıma

Dosya taşımak için Windows Gezgini ile dosya(lar) seçilir. Seçili nesneler sağ tuşa tıklanarak taşınmak istenen yeni dizine sürüklenir.Açılan menüden "svn move versioned item(s) here" seçilir.

SVN Checkout
SVN'e dahil olmayan bir dizine sağ veya boş bir yere sağ tıklanınca "SVN Checkout" menüsü gelir. Menüyü seçince "Checkout" kutusu açılır. Repository adresi girildikten sonra - örneğin "svn://10.5.91.179/Projem" gibi - dosyalar seçtiğimiz dizine indirilirler.

Ayarları Temizlemek
Tortiose Svn bazı ayarları kaydeder. Örneğin kullanıcı şifresi gibi. Bu tür şeyleri temizlemek için Tortoise svn / Settings / Saved Data menüsünü seçin. Authentication data yazısının yanındaki "Clear" düğmesine tıklayın.

Komut Satırından Çalıştırma
TortoiseSVN bir GUI programı ancak komut satırından TortoiseProc.exe kullanılarak aşağıdaki gibi çalıştırılabilir.
<Path to TortoiseSVN>\bin\TortoiseProc.exe /command:<SVNCommand> <Parameters>
closeonend seçeneği
TortoiseSVN ekrana popup birşeyler çıkarabilir. closeonend seçenekleri kullanılırsa otomasyon daha kolay yapılabilir.

/closeonend:0 don't close the dialog automatically
/closeonend:1 auto close if no errors
/closeonend:2 auto close if no errors and conflicts
/closeonend:3 auto close if no errors, conflicts and merges

command seçenekleri

checkout
Tüm projeyi en baştan bir kere checkout eder. Kod büyükse uzun sürebilir.
tortoiseproc /command:checkout /path:D\:MyProject /url:http://subversion/myproject/trunk/code /noninteractive

update
checkout komutu ile aynı. Sadece değişen dosyaları indirir. Revizyon ve diğer ıvır zıvır seçenekleri hiç kullanmadım.
Updates the working copy in /path to HEAD

tortoiseproc /command:update /path:D\:MyProject /url:http://subversion/myproject/trunk/code /noninteractive

repostatus
Eğer Update komutu çalıştırılınca hangi dosyaların indirileceğini görmek istersek aşağıdaki gibi yapabiliriz.Açıklaması şöyle:
Opens the check-for-modifications dialog. The /path specifies the working copy directory. If /remote is specified, the dialog contacts the repository immediately on startup, as if the user clicked on the Check repository button.

tortoiseproc /command:repostatus /path:D\:MyProject /remote

SVN Sunucusunu Kilitleme
SVN sunucusu admin tarafından kilitlenebilir. Böylece commit yapılması önlenebilir.

_controlfp metodu

Giriş
Bu metod yerine _controlfp_s() metodunu kullanmak daha iyi.

Örnek
C#'ta X87 FPU'nun precision değerini değiştirmek için şöyle yaparız.
using System;
using System.Runtime.InteropServices;

static void Main()
{
  double s = -2.6114289999999998;

  Console.WriteLine(Math.Round(s, 7).ToString("R")); // -2.611429

  if (!Environment.Is64BitProcess)
    _controlfp(0x00030000, 0x00020000);

  Console.WriteLine(Math.Round(s, 7).ToString("R")); // -2.61142897605896
}

[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
static extern uint _controlfp(uint newcw, uint mask);

_controlfp_s metodu

Giriş
Bu metod _controlfp() metodunun daha güvenli (secure) hali.

Örnek
Şöyle yaparız
// Get control word
_controlfp_s(&cw, 0, 0); // Line A

// Enable zero-divide exception
_controlfp_s(0, ~_EM_ZERODIVIDE, _MCW_EM); // Line B
Örnek
C#'ta şöyle yaparız.. Önce metodları import ederiz.
internal static class SafeNativeMethods
{
  [DllImport("msvcr120.dll")]
  public static extern void _fpreset();

  [DllImport("msvcr120.dll", CallingConvention = CallingConvention.Cdecl)]
  public static extern int _controlfp_s(
        out int currentControl, int newControl, int mask);

  public static int _CW_DEFAULT = 
        (_RC_NEAR | _PC_53 | _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW 
        | _EM_UNDERFLOW | _EM_INEXACT | _EM_DENORMAL);

  public const int _MCW_EM = 0x0008001f;          // interrupt Exception Masks 
  public const int _EM_INEXACT = 0x00000001;      //   inexact (precision) 
  public const int _EM_UNDERFLOW = 0x00000002;    //   underflow 
  public const int _EM_OVERFLOW = 0x00000004;     //   overflow 
  public const int _EM_ZERODIVIDE = 0x00000008;   //   zero divide 
  public const int _EM_INVALID = 0x00000010;      //   invalid 
  public const int _EM_DENORMAL = 0x00080000;     // denormal exception mask 
                                                    // (_control87 only) 

  public const int _MCW_RC = 0x00000300;          // Rounding Control 
  public const int _RC_NEAR = 0x00000000;         //   near 
  public const int _RC_DOWN = 0x00000100;         //   down 
  public const int _RC_UP = 0x00000200;           //   up 
  public const int _RC_CHOP = 0x00000300;         //   chop 

  public const int _MCW_PC = 0x00030000;          // Precision Control 
  public const int _PC_64 = 0x00000000;           //    64 bits 
  public const int _PC_53 = 0x00010000;           //    53 bits 
  public const int _PC_24 = 0x00020000;           //    24 bits 

  public const int _MCW_IC = 0x00040000;          // Infinity Control 
  public const int _IC_AFFINE = 0x00040000;       //   affine 
  public const int _IC_PROJECTIVE = 0x00000000;   //   projective 
}
Sonra şöyle yaparız.
int fpFlags;
var errno = SafeNativeMethods._controlfp_s(out fpFlags, 0, 0);
if (errno != 0)
{
  throw new Win32Exception(
    errno, "Unable to retrieve floating-point control flag.");
}

if ((fpFlags & SafeNativeMethods._MCW_PC) != SafeNativeMethods._PC_64)
{
  Trace.WriteLine("Change floating-point precision to 64 bit");
  errno = SafeNativeMethods._controlfp_s(
    out fpFlags, SafeNativeMethods._PC_64, SafeNativeMethods._MCW_PC);

  if (errno != 0)
  {
    throw new Win32Exception(
      errno, "Unable to change floating-point precision to 64 bit.");
  }

}
İlk haline getirmek için şöyle yaparız.
Trace.WriteLine("Resetting floating-point precision to default");
SafeNativeMethods._fpreset();




IEEE 754 - Extended Precision

X87 - 32 bit Derleme
Açıklaması şöyle.
On x64, the SSE2 FPU is used and on x86 the x87 FPU is used.
X87'deki FPU 80 bit. Ancak çeşitli uzunluklarda (64 veya 80 bit) çalışmak üzere programlanabiliyor.
Açıklaması şöyle
It is possible (although not advised) to change the x87 precision to be the same as the SSE2 precision (i.e., use lower precision).
fdiv
Sanırım bölme işlemi yapıyor.

fistp
float -> int çevrimi için kullanılır.

mov
Kullanım şekli şöyle.
mov mem, reg
mov reg, mem
mov reg, reg
mov reg, imm
mov mem, imm
Açıklaması şöyle
Most x86 instructions (other than some specialized instructions such as movsb) can only access one memory location. Therefore a move from memory to memory requires going through a register with two mov instructions.
Elimizde şöyle bir kod olsun
x = y;
Assembly kodu şöyledir
movl    -0x8(%rbp), %esi
movl    %esi, -0xc(%rbp)
Streaming SIMD Extensions 2 - SSE2 - 64 bit Derleme
Visual Studio 2012'den itibaren 64 bit kodlar için SSE2 kodları üretiyor. SSE2 kodları XMM yazmaçlarını kullanır. Assembly kodu şöyledir
movsd   QWORD PTR [rsp+8], xmm1
call    cos
movsd   xmm1, QWORD PTR [rsp+8]
movsd   QWORD PTR [rsp], xmm0
movapd  xmm0, xmm1
call    cos
movsd   xmm2, QWORD PTR [rsp]
ucomisd xmm2, xmm0
divss
Sanırım bölme işlemi yapıyor. gcc'de şöyle yaparız.
__m128 s1, s2;
s1 = _mm_set_ps(1.0, 1.0, 1.0, 1.0);
s2 = _mm_set_ps(0.0, 0.0, 0.0, 0.0);
s2 = _mm_div_ss(s1, s2);
_mm_loadu_si128 
Elimizde bir dizi olsun.
short* tempBufferVert = new short[width * height];
Dizideki her elemanı 4 il bölmek için şöyle yaparız.
#include <emmintrin.h> // SSE2

for (int i = 0; i < width * height; i += 8)
{
  __m128i v = _mm_loadu_si128((__m128i *)&tempBufferVert[i]);
  v = _mm_srai_epi16(v, 2); // v >>= 2
  _mm_storeu_si128((__m128i *)&tempBufferVert[i], v);
}
setcsr
Şöyle yaparız.
_mm_setcsr (0x00001D80);
Intel 80 bit floating point
80 bitlik precision bazı C++ derleyicileri tarafından kullanılabiliyor. Aşağıdaki cümlede bunu okuyabiliriz.
The C++ standard allows implementations to evaluate floating-point expressions with more precision than the nominal type requires.
Bir başka açıklama şöyle
The IEEE 754 specifies that computations can be processed at a higher precision than what is stored in memory then rounded when written back to memory ..... In short, the standard does not promise that the same computation carried out on all hardware will return the same answer.
Örnek
Aşağıdaki basit örnekte derleyicinin iki double sayısını çarparken fazla precision kullandığını görebiliriz.
#include <cstdint>
#include <cinttypes>
#include <cstdio>

using namespace std;

int main() {
    double xd = 1.18;
    int64_t xi = 1000000000;

    int64_t res1 = (double)(xi * xd);

    double d = xi * xd;
    int64_t res2 = d;

    printf("%" PRId64"\n", res1);
    printf("%" PRId64"\n", res2);
}
Çıktı olarak şunu alırız.
1179999999
1180000000
Örnek
32 ve 64'bitlik uygulamalar arasında da farklar olabilir.
long double dvalue = 2.7182818284589998;
long double dexp = -0.21074699576017999;
long double result = std::powl( dvalue, dexp)
Sonuç olarak şunu alırız.
64bit -> result = 0.80997896907296496 and 32bit -> result = 0.80997896907296507
FPU içindeki kayan nokta hesaplaması için kullanılan register'lar 80 bit olabiliyor.

C ile kullanılan long double 80 bitlik bu veri tipine denk gelebilir. Bu durumda iki farklı makine arasında aynı hesaplamayı yapsak bile farklı sonuçlar elde edilebilir. Derleyiciler strict mode çalışmaya zorlanarak farklı makineler arasında aynı sonucu elde etmek mümkün.

C++
1. /fp:precise - MS derleyici için kullanılır
Varsayılan seçenek budur. Açıklaması şöyle
fp:precise weakens some of the rules, however it warranties that the precision of the calculations will not be lost.
Ara değerlerin (intermediate value) FPU registerlarında saklanmasına müsaade etmez. Hesaplamadan sonra ara değerler bellekteki alana geri yazılır. Açıklaması şöyle özellike x87 kodlarında bu açıklama önemli.
If the value to be computed on is placed on a larger register then one computation is done and then the value is moved off of the register back to memory the result is truncated there. It could then be moved back on to the larger register for another computation.
On the other hand if all the computations are done on the larger register before the value is moved back to memory you will get a different result.
Bu seçenek Visual C++ 6.0 ile kullanılan /Op (Improve Float Consistency) seçeneğinin yerini almıştır. Eski seçenek için de benzer bir açıklama Açıklaması şöyleydi
By default, the compiler uses the coprocessor’s 80-bit registers to hold the intermediate results of floating-point calculations. This increases program speed and decreases program size. However, because the calculation involves floating-point data types that are represented in memory by less than 80 bits, carrying the extra bits of precision (80 bits minus the number of bits in a smaller floating-point type) through a lengthy calculation can produce inconsistent results.
2. /fp:strict - MS derleyici için kullanılır
Platformlar arasında uyumluluğu sağlamak için yukarıdaki gibi 80 bitlik floating point hesaplamalarını kullanılmaz. Açıklaması şöyle
Using fp:strict means that all the rules of IEEE 754 are respected. fp:strict is used to sustain bitwise compatibility between different compilers and platforms.

Java
strictfp expression kullanılabilir veya StrictMath kütüphanesi kullanılabilir. Örnek:
public strictfp class MyFPclass { 
    // ... contents of class here ...
}

3. /fp:fast
Açıklaması şöyle
fp:fast allows compiler specific optimizations and transformations of expressions containing floating point calculation. It is the fastest methods but the results will differ between different compilers and platforms.